1. 程式人生 > >自己選擇的路,跪著也要走完。

自己選擇的路,跪著也要走完。

洛谷3381,最小費用最大流模板題

輸入格式:

第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。

接下來M行每行包含四個正整數ui、vi、wi、fi,表示第i條有向邊從ui出發,到達vi,邊權為wi(即該邊最大流量為wi),單位流量的費用為fi。

輸出格式:

一行,包含兩個整數,依次為最大流量和在最大流量情況下的最小費用。

#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
const int maxn=5005;
const int maxm=50005;
int n,m,s,t;   //點的個數,邊的個數,源點,匯點
int num=-1,tot,sum; //tot是最大流  sum是在最大流條件下的最小費用
int dis[maxn],b[maxn],xb[maxn],flow[maxn],fa[maxn];
int head[maxm];
struct Edge
{
    int from,to,dis,nxt,w;
}edge[maxm*2];//要建立反向邊,所以這裡要*2

void add_edge(int from,int to,int w,int dis)
{
    edge[++num].nxt=head[from];
    edge[num].from=from;
    edge[num].to=to;
    edge[num].w=w;
    edge[num].dis=dis;
    head[from]=num;
}


/*void add(int from,int to,int w,int dis)
{
    add_edge(from,to,w,dis);
    add_edge(to,from,0,-dis);
}*/


bool spfa()
{
    for(int i=0;i<=maxn;i++) //初始化1-n的dis陣列
        dis[i]=inf;
    memset(b,0,sizeof(b));
    queue<int>que;
    while(!que.empty()) que.pop();
    memset(fa,-1,sizeof(fa));
    b[s]=1;
    dis[s]=0;
    fa[s]=0;
    flow[s]=inf;
    que.push(s);
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        b[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(edge[i].w>0&&dis[v]>dis[u]+edge[i].dis)
            {
                dis[v]=dis[u]+edge[i].dis;
                fa[v]=u;
                xb[v]=i;
                flow[v]=min(flow[u],edge[i].w);
                if(!b[v])
                {
                   b[v]=1;
                   que.push(v);
                }
            }
        }
    }
    return dis[t]<inf;
}

void max_flow()
{
   while(spfa())
   {
       int k=t;
       while(k!=s)
       {
           edge[xb[k]].w-=flow[t];
           edge[xb[k]^1].w+=flow[t];
           k=fa[k];
       }
       tot+=flow[t];
       sum+=flow[t]*dis[t];
   }
}

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d %d %d %d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
        int a,b,c,d;
        scanf("%d %d %d %d",&a,&b,&c,&d);//有向邊起點,終點,邊的流量,單位流量的費用
        add(a,b,c,d);
    }
    max_flow();
    cout<<tot<<" "<<sum<<endl; //tot是最大流,sum是在最大流條件下的最小費用*/
}

例:

CCPC-Wannafly Summer Camp #1——A——Birthday(最小費用最大流)

題意:把n個蛋糕放到m個區域裡,每個蛋糕都有兩種區域可以放,總花費為所有區域蛋糕數量的平方和,要求花費盡量小。

解法:想到把每個區域都拆成n個點,如果某一蛋糕可以放到一個區域裡,就把蛋糕和這對應的點都連邊,流量為1,連第i個點的代價是f(i)-f(i-1),f(x)=x*x。然後建立超級源點和超級匯點,源點與所有蛋糕連邊且流量為1,費用為0,匯點與所有區域連邊且流量為1,費用為0。跑一遍最小費用最大流,最後得出的費用即是ans。

#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
const int maxn=5005;
const int maxm=50005;
int s,t;   //點的個數,邊的個數,源點,匯點
int num=-1,tot,sum; //tot是最大流  sum是在最大流條件下的最小費用
int dis[maxn],b[maxn],xb[maxn],flow[maxn],fa[maxn];
int head[maxm];
struct Edge
{
    int from,to,dis,nxt,w;
}edge[maxm*2];//要建立反向邊,所以這裡要*2

void add_edge(int from,int to,int w,int dis)
{
    edge[++num].nxt=head[from];
    edge[num].from=from;
    edge[num].to=to;
    edge[num].w=w;
    edge[num].dis=dis;
    head[from]=num;
}


/*void add(int from,int to,int w,int dis)
{
    add_edge(from,to,w,dis);
    add_edge(to,from,0,-dis);
}*/


bool spfa()
{
    for(int i=0;i<=maxn;i++) //初始化1-n的dis陣列
        dis[i]=inf;
    memset(b,0,sizeof(b));
    queue<int>que;
    while(!que.empty()) que.pop();
    memset(fa,-1,sizeof(fa));
    b[s]=1;
    dis[s]=0;
    fa[s]=0;
    flow[s]=inf;
    que.push(s);
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        b[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(edge[i].w>0&&dis[v]>dis[u]+edge[i].dis)
            {
                dis[v]=dis[u]+edge[i].dis;
                fa[v]=u;
                xb[v]=i;
                flow[v]=min(flow[u],edge[i].w);
                if(!b[v])
                {
                   b[v]=1;
                   que.push(v);
                }
            }
        }
    }
    return dis[t]<inf;
}

void max_flow()
{
   while(spfa())
   {
       int k=t;
       while(k!=s)
       {
           edge[xb[k]].w-=flow[t];
           edge[xb[k]^1].w+=flow[t];
           k=fa[k];
       }
       tot+=flow[t];
       sum+=flow[t]*dis[t];
   }
}

int main()
{
    memset(head,-1,sizeof(head));
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int a,b;
        cin>>a>>b;
        for(int j=1;j<=n;j++)
        {
            add_edge(i,n+(j-1)*m+a,1,2*j-1);
            add_edge(n+(j-1)*m+a,i,0,1-2*j);
            add_edge(i,n+(j-1)*m+b,1,2*j-1);
            add_edge(n+(j-1)*m+b,i,0,1-2*j);
        }
    }
    for(int i=1;i<=n;i++)
    {
        add_edge(0,i,1,0);
        add_edge(i,0,0,0);
    }
    for(int i=n+1;i<=n+n*m;i++)
    {
        add_edge(i,n+n*m+1,1,0);
        add_edge(n+n*m+1,i,0,0);
    }
    s=0;
    t=n+n*m+1;
    max_flow();
    cout<<sum<<endl;
}

洛谷3376 最大流模板題

輸入格式:

第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。

接下來M行每行包含三個正整數ui、vi、wi,表示第i條有向邊從ui出發,到達vi,邊權為wi(即該邊最大流量為wi)

輸出格式:

一行,包含一個正整數,即為該網路的最大流。

EK演算法目前在演算法競賽中幾乎廢棄,這裡我們使用弧優化的dinic演算法已經非常快了,雖然最大流的最快演算法可能還是IASP,但是一般不會出現只能IASP過而卡dinic的演算法的。

#include<bits/stdc++.h>
using namespace std;
const int maxn=10005;
const int maxm=100005;
const int inf=1e9;
int cnt=-1,n,m,s,t;  //點和邊的個數,起點和終點的編號
int head[maxn],dep[maxn],cur[maxn];
struct Edge
{
    int next=-1;
    int to,w;
} edge[2*maxm]; //next初始值是-1,有反向邊所以開了2倍陣列
void add_edge(int u,int v,int w)
{
    edge[++cnt].next=head[u];
    edge[cnt].to=v;
    edge[cnt].w=w;
    head[u]=cnt;
}
bool bfs()
{
    queue<int>que;
    while(!que.empty()) que.pop();
    memset(dep,0,sizeof(dep));
    dep[s]=1;
    que.push(s);
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to;
            if((dep[v]==0)&&edge[i].w>0)
            {
                dep[v]=dep[u]+1;
                que.push(v);
            }
        }
    }
    if(dep[t]>0)
        return 1;
    return 0;
}
int dfs(int u,int flow)
{
    if(u==t) return flow;
    for(int &i=cur[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].to;
        if ((dep[v]==dep[u]+1)&&(edge[i].w!=0))
        {
            int d=dfs(v,min(flow,edge[i].w));
            if (d>0)
            {
                edge[i].w-=d;
                edge[i^1].w+=d;
                return d;
            }
        }
    }
    return 0;
}
int Dinic()
{
    int ans=0;
    while (bfs())
    {
        for (int i=1; i<=n; i++) 
            cur[i]=head[i];
        while (int d=dfs(s,inf))
        {
            ans+=d;
        }
    }
    return ans;
}
int main()
{
    memset(head,-1,sizeof(head));
    cin>>n>>m>>s>>t; //輸入資訊可能會隨題目改變而不一樣,請注意隨機應變
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add_edge(a,b,c);
        add_edge(b,a,0);//反向邊流量是0,切不可記作-c。
    }
    cout<<Dinic()<<endl;
    return 0;
}

相關推薦

自己選擇

洛谷3381,最小費用最大流模板題 輸入格式: 第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。 接下來M行每行包含四個正整數ui、vi、wi、fi,表示第i條有向邊從ui出發,到達vi,邊權為wi(即該邊最大流量為wi),單位流

自己選擇就算

 最近寫了一個多星期的並查集,一瞬間貼出這麼多解題報告,我想關於並查集的應用先告一段落吧,先總結一下。 在網上看到一篇關於並查集比較好的教程(姑且允許我這麼說吧),不轉過來是在可惜。獻給愛學習的你 文章作者:Slyar 文章來源:Slyar Home (www.s

【伊克賽艇旗艦店】自己選擇,就算

DH ---------以上初三THU/PKU大爺---- Alan_cty LYD XHM HZJ ZZ ---以下是大神%-- YMW Samjia2000 werkeytom_ftd Crazy_czy WorldWide_D Yxuan

自己挖的坑---mapper配置檔案和java原始檔在同一包下

本來準備研究下mybatis原始碼執行流程的,就隨意搭建了個專案,所有配置如下:     一切看似都是那麼的正常,然而執行的時候:Exception in thread "main" org.apache.ibatis.binding.BindingException:

再難下去因為我想看看這條的盡頭是什麼

知乎上有一個人回答這個問題回答的很好,特附上鍊接:為什麼不能在ArrayList的For-Each迴圈中刪除元素 - 南山伐木的文章 - 知乎http://zhuanlan.zhihu.com/p/25744271下面是我的理解:a. For-Each遍歷是基於ArrayLi

奮鬥吧 自己

1.什麼是標籤選擇器? 作用:根據指定的標籤名,在當前介面中找到所有該名稱的標籤,然後設定屬性。 格式: 標籤名{ 屬性:值; } 注意點: 1. 標籤選擇器選定的是當前介面中所有該名稱的標籤,而不能單獨選定某一標籤; 2. 標籤選擇器無論標籤藏得多深都能找到; 3. 只要

既認準這條又何必在意多久

自己遇到這樣的東西 先大概寫了一個模型 用的swfupload+struts 或者單獨的 swfupload +serverlet  檔案在程式中的位置具體如下: 必須的包:lib裡面的包都是必須的。 索要引用的js 有 jquery和 handlers(主要就是控

借錢債 ——獻給不守信用的人

記得十幾年前,在臺灣看的第一部大陸劇「雍正王朝」,印象最深的是,康熙命雍正負責追回國庫欠款,雍正面對那群厚顏無恥的欠債官員,說了一句很經典的話:「站著借錢,跪著要債」。 現在的社會現象亦是如此,你好心借錢給朋友應急,對方說好很快就還,結果⋯日復一日,月復一月,都年底了,

即使沒人註視努力成長許多眼睛都藏在你看不見的地方!

希望 一起 單詞 發出 今天 logs 眼睛 cnblogs .com 更新一下今天的學習進度:以後每天都會更新,倘若有啥感悟想說的話也會一起發出來,希望更多的人能和我一起堅持下去:   1.每天背誦50個英文單詞,復習鞏固了52個單詞,進度: 1350/348

兩個按鈕相關聯:改變員工級別其對應的薪資相應改變(框架要求:SSM )

碰到一個需求: 升遷時:只允許修改僱員級別與部門編號,或新增部門,其他欄位不能修改.僱員底薪要相應改變. js介面獲取的值如下:員工級別從字典中獲取到,把級別對應的底薪用datalist顯示,往action傳的值為對應的員工級別; <tr> <td&

財路網每日原創推送:終於按捺不住騰訊上交易所發幣?

據CCN最新訊息稱,騰訊遊戲已經宣佈與區塊鏈電子競技娛樂平臺SLIVER.tv合作,建立一個電子競技直播頻道。據財路網記者查閱相關資料顯示,該頻道還發行了自己的代幣Theta,而且還在眾多知名交易所上市交易了,這是不是意味著騰訊在變相上交易所發幣呢? 與區塊鏈遊戲直播合作據悉,騰訊合作的這個平臺是一個全

PHP socket初探 --- 含libevent(三)

這段時間相比大家也看到了,本人離職了,一是在家偷懶實在懶得動手,二是好不容易想寫點兒時間全部砸到資料結構和演算法那裡了。 今兒回過頭來,繼續這裡的文章。那句話是怎麼說的: “自己選擇的課題,含著淚也得磕完!”(圖文無關,詳情點選這裡)。 其實在上一篇libeve

docker(23):在windows 上面安裝使用docker挺方便的

1,關 於docker docker 是非常方便的。 之前都是在 linux 在 mac 上面使用,那個還是非常方便的。 在windows上面限制比較多。 1,必須是windows 10 作業系統 2,開啟bios的intel v

【且行且珍惜】一個人久了害怕孤獨卻又一個人享受孤獨的滋味總愛在一個人的時候把自己搞得很悲情然後放聲大哭像個小孩子一樣在獨自欣賞一種叫做殘酷的美心情瞬息萬變發洩心裡所有的不滿

且行且珍惜 一個人久了,害怕孤獨卻又一個人享受著孤獨的滋味,總愛在一個人的時候把自己搞得很悲情,然後放聲大哭,像個小孩子一樣,在獨自欣賞著一種叫做殘酷的美。心情瞬息萬變,發洩著心裡所有的不滿。 ...

“媽媽我不想學了”你的回答改變孩子一生(悵然若失說了一句話:“為什麼當初沒有人逼我?”我不願意學你就不讓我學啦!那時候我還小我還不懂事難道你不懂事嗎。要做成一件事就必須有延遲滿足的能力)

“媽媽,我不想學了”,你的回答改變孩子一生(組圖)新聞來源: 槽值 前兩天,送孩子去書法班的時候,在小區門口看到一位媽媽,她正拽著孩子往車裡進,孩子哭著掙扎:“我不想學舞蹈了,我不去,太累了……” 媽媽怒吼著:“你今天去也得去,不去也得給我去!” 最終,孩子還是拗不過媽媽,上了車,去學舞蹈。 我不禁想

男人不想打工一輩子再忙讀這10本書提高情商智商

作為一個男性,在社會總要承擔很多很多,來自於家庭,社會的壓力,常常讓人喘不過氣來,而作為家庭的主心骨,我們必須養家餬口,因為你不努力,沒人替你撐住這片天。 是啊,男人太累了,但是身為男人,累是不能抱怨的,因為這就是我們的責任,身為男人就要努力去拼搏,為自己為家人贏得一份幸福感,相信每一個真男人都有

如何把asp.net網站釋出到自己的電腦外網可以訪問

IIS元件安裝 把自己寫好的asp.net網站釋出到IIS上面 測試內網下是否可以訪問 配置路由器的埠對映 測試外網下是否也可以訪問 IIS元件安裝 第一步 進入控制面板–>程式–>啟用和關閉windows功能 選擇劃線的部分,勾選的

統計兩個日期之間的資料(平均數總數無資料顯示日期資料預設顯示為0

JAVA開發時有這麼一個需求:給一個開始時間和一個結束時間,顯示這段時間內每一天的資料,這個SQL語句並不大難(用一個GROUP BY就可以搞得定),關鍵點在於前臺頁面要顯示折線圖,所以沒有資料時日期也是要顯示的。在網上查了很多資料後,現總結如下,方便自己,也給大家提供一個思

憤怒是會傳染的即使遇上不順心的事保持微笑

一,路過心靈上的故事   那天,我站在一個珠寶店的櫃檯前,把一個裝著幾本書的包放在旁邊,在我挑選珠寶時,一個衣著講究的男士也過來看珠寶,我禮貌的把我的包移開,但這個人卻憤怒的瞪著我,告訴我他是正人君子,絕對無意偷我的包,他覺得他受到了侮辱,走出了珠寶店,重重的把門摔上。“哼,

又有肆意的笑眼角的泛淚

真的 口水 一個 一份 都是 我不 個人 一點 速度 之前在小號裏發過一條說說,雖然之前早就想過會有這麽一天。沒想到這麽快就到了,時間真快。我也老了半學期啊。 現在,在面前的講義上,那一片印記不再是看睡著留下的口水,而是淚水滴在其上了。 舍不得,真的舍不得。但我又很開心,真