bzoj4514 數字配對

来源:https://www.cnblogs.com/wxyww/archive/2019/02/17/bzoj4514.html
-Advertisement-
Play Games

思路 首先想到費用流。 對於每個點拆點。然後考慮我們怎樣才能保證每個點只被用一次。 如果$i$與$j$滿足條件。那麼就從$i$向$j$連一條邊並且從$j$向$i$連一條 ...


思路

首先想到費用流。
對於每個點拆點。然後考慮我們怎樣才能保證每個點只被用一次。
如果\(i\)\(j\)滿足條件。那麼就從\(i\)\(j\)連一條邊並且從\(j\)\(i\)連一條邊。這樣每次增廣的時候我們都可以看作某一條邊被增廣了兩次。顯然從\(i\)\(j\)和從\(j\)\(i\)的邊是等價的。也就是說,如果當前增廣這兩個點之間的邊更優秀,那麼在增廣完成從\(i\)\(j\)和從\(j\)\(i\)這兩條邊流量變為\(0\)之前不回去增廣其他的邊。
比較難解釋,仔細想一下可以發現是對的。這樣最後我們找出的流量實際上是答案的兩倍。除二即可。
然後還要考慮題目中對於價值的限制。我們把價值當作費用,每次增廣費用最大的路徑。直到如果再增廣費用變為負數為止。

代碼

/*
* @Author: wxyww
* @Date:   2019-02-17 14:52:25
* @Last Modified time: 2019-02-17 19:36:45
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 410,M = 1000000 + 100,INF = 1e9;
ll read() {
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
struct node {
    int v,nxt,w;
    ll cost;
}e[M];
int head[N],ejs = 1;
void add(int u,int v,int w,ll c) {
    e[++ejs].v = v;e[ejs].w = w;e[ejs].cost = c;e[ejs].nxt = head[u];head[u] = ejs;
    e[++ejs].v = u;e[ejs].w = 0;e[ejs].cost = -c;e[ejs].nxt = head[v];head[v] = ejs;
}
int a[N],vis[N],fa[N],b[N];
ll dis[N],c[N];
queue<int>q;
int S,T;
bool pd(int x,int y) {
    if(x < y) swap(x,y);
    if(!y || x == y) return false;
    if(x % y) return false;
    int k = x/y;
    for(int i = 2;i * i <= k;++i)
        if(k % i == 0) return false;
    return true;
}
bool spfa() {
    while(!q.empty()) q.pop();
    memset(dis,-0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(fa,0,sizeof(fa));
    q.push(S);dis[S] = 0;
    while(!q.empty()) {
        int u = q.front();q.pop();vis[u] = 0;
        for(int i = head[u];i;i = e[i].nxt) {
            int v = e[i].v;
            if(dis[v] < dis[u] + e[i].cost && e[i].w) {
                dis[v] = dis[u] + e[i].cost;
                fa[v] = i;
                if(!vis[v]) q.push(v),vis[v] = 1;
            }
        }
    }
    return fa[T];
}
ll dinic() {
    ll COST = 0,FLOW = 0;
    while(spfa()) {
        int mn = INF;
        for(int i = fa[T];i;i = fa[e[i ^ 1].v]) mn = min(mn,e[i].w);
        for(int i = fa[T];i;i = fa[e[i ^ 1].v]) e[i].w -= mn,e[i ^ 1].w += mn;
        if(COST + dis[T] * mn < 0) {
            FLOW += COST / -dis[T];
            return FLOW;
        }
        COST += dis[T] * mn;
        FLOW += mn;
    }
    return FLOW;
}
int main() {
    int n = read();
    for(int i = 1;i <= n;++i) a[i] = read();
    for(int i = 1;i <= n;++i) b[i] = read();
    for(int i = 1;i <= n;++i) c[i] = read();
    S = n * 2 + 1,T = S + 1;
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
            if(i != j && pd(a[j],a[i]))
                add(i,j + n,INF,c[i] * c[j]);
    int tot = ejs;
    for(int i = 1;i <= n;++i) add(S,i,b[i],0);
    for(int i = 1;i <= n;++i) add(i + n,T,b[i],0);
    cout<<(dinic() >> 1);
    return 0;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 《c陷阱與缺陷》 編程者也許認為,程式一旦執行上述操作完畢,就可以自由地進行讀取和寫入的操作了。遺憾的是,事實總難遂人所願,為了保持與過去不能同時進行讀寫操作的程式的向下相容性,一個輸入操作不能隨後直接緊跟輸出操作,反之亦然。如果同時進行輸入和輸出操作,必須在其中插入fseek函數調用。 這個陷阱把 ...
  • 題意 "題目鏈接" Sol 說一個尾碼自動機+線段樹的無腦做法 首先建出SAM,然後對parent樹進行dp,維護最大次大值,最小次小值 顯然一個串能更新答案的區間是$[len_{fa_{x}} + 1, len_x]$,方案數就相當於是從$siz_x$裡面選兩個,也就是$\frac{siz_x ( ...
  • 註意:本 Spring Boot 系列文章基於 Spring Boot 版本 v2.1.1.RELEASE 進行學習分析,版本不同可能會有細微差別。 前言 關於配置文件可以配置的內容,在 "Spring Boot 官方網站" 已經提供了完整了配置示例和解釋。 可以這麼說,Spring Boot 的一 ...
  • import randomimport sysimport zipfileimport timefrom threading import Threadfrom multiprocessing import Processclass MyIterator: # letters = '01234567... ...
  • Go語言是Google公司在2009年開源的一門高級編程語言,它為解決大型系統開發過程中的實際問題而設計,支持併發、規範統一、簡單優雅,被很多Go語言傳道者譽為“互聯網時代的C語言”。而C++語言誕生於1979年,可以將C++語言視為一個語言聯邦,主要包含C語言(面向過程)、面向對象、STL容器和算 ...
  • 最近複習JVM的知識,對於靜態分派和動態分派的理解有點混亂,於是自己嘗試寫寫代碼,在分析中鞏固知識。 有如下一段代碼,請問每一段分別輸出什麼? 下麵我簡單地介紹一下從代碼編譯到方法調用的整個過程。 · 編譯 先看看第1段輸出,child.foo()是調用父類還是子類的靜態方法呢? 在編譯階段,發生了 ...
  • 看門見山 1.java中replace API: replace(char oldChar, char newChar):寓意為:返回一個新的字元串,它是通過用 newChar 替換此字元串中出現的所有 oldChar 得到的。 replace(CharSequence target, CharSe ...
  • 比如我們有個列表: 如果我們需要將列表裡的元素轉換為數字呢?最常用的大家可能會想到使用列表推導式: 輸出:[1, 2, 3, 4] 還有一種技巧,更方便: 輸出:[1, 2, 3, 4] ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...