BZOJ 3511: 土地劃分 最小割
3511: 土地劃分
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 255 Solved: 146
[Submit][Status][Discuss]
Description
Y國有N座城市,並且有M條雙向公路將這些城市連線起來,並且任意兩個城市至少有一條路徑可以互達。
Y國的國王去世之後,他的兩個兒子A和B都想成為新的國王,但他們都想讓這個國家更加安定,不會用武力解決問題。
於是他們想將這個國家分成兩個小國家A國和B國。現在,A擁有1號城市,B擁有N號城市,其他的城市還尚未確定歸屬哪邊(劃分之後的國家內部城市可以不連通)。
由於大家都想讓國家變得更好,而某些城市的人民願意國王的A兒子作為他們的領袖,而某些城市更看好B,而為了交通的便捷,如果劃分後的公路連線兩個同一個國家的城市,那麼更利於城市之間的交流。於是大臣們設計了一種對土地劃分的評分機制,具體如下:
1. 對於城市i,如果它劃分給A國,將得到VA[i]的得分;劃分給B國,將得到VB[i]的得分。
2. 對於一條公路i,如果它連線兩個A國的城市,將得到EA[i]的得分;連線兩個B國的城市,將得到EB[i]的得分;否則,這條公路將失去意義,將扣除EC[i]的得分。
現請你找到最優的土地劃分,使得這種它的評分最高。
Input
第一行包含兩個整數N,M,含義如問題描述所示。
接下來一行N-2個非負整數,表示VA[2..N-1]。
接下來一行N-2個非負整數,表示VB[2..N-1]。
接下來M行,每行五個非負整數描述一條公路:X Y EA[i] EB[i] EC[i],含義如問題描述所示。
Output
輸出有且僅有一個整數,表示最高評分。
Sample Input
3 38
9
1 2 2 6 2
2 3 8 5 7
1 3 9 4 1
Sample Output
11【樣例說明
A國僅有1號點,B國有2號和3號點。
評分=VB[2]+EB[2]-EC[1]-EC[3]=9+5-2-1=11。
HINT
【資料說明】
資料點 N M 備註
1-2 <=20 <=200 無
3-4 <=5000 <=10000 VA、VB、EA、EB均為0
5-6 <=5000 <=10000 EC均為0
7-10 <=10000 <=40000 無
保證運算過程中及最終結果不超過32位帶符號整數型別的表示範圍
有經驗的很快就看出是最小割
#include<cmath> #include<ctime> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<iomanip> #include<vector> #include<string> #include<bitset> #include<queue> #include<set> #include<map> using namespace std; typedef long long ll; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } void print(int x) {if(x<0)x=-x,putchar('-');if(x>=10)print(x/10);putchar(x%10+'0');} const int N=100100,inf=0X3f3f3f3f; int ecnt=1,last[N]; struct EDGE{int to,nt,val;}e[10001000]; inline void readd(int u,int v,int val) {e[++ecnt]=(EDGE){v,last[u],val};last[u]=ecnt;} inline void add(int u,int v,int val) {readd(u,v,val);readd(v,u,0);} int tot,n,m,S=0,T=N-1; int q[N],d[N]; bool bfs() { memset(d,0,sizeof(d)); register int head=0,tail=1,u,i; d[S]=1;q[head]=S; while(head<tail) { u=q[head++]; for(i=last[u];i;i=e[i].nt)if(e[i].val&&!d[e[i].to]) { d[e[i].to]=d[u]+1; q[tail++]=e[i].to; } } return d[T]; } int dfs(int u,int lim) { if(!lim||T==u){return lim;} int res=0,tmp; for(int i=last[u];i;i=e[i].nt) if(d[e[i].to]==d[u]+1&&e[i].val) { tmp=dfs(e[i].to,min(e[i].val,lim)); lim-=tmp;res+=tmp;e[i].val-=tmp;e[i^1].val+=tmp; if(!tmp)d[e[i].to]=-1;if(!lim)break; } return res; } int mxflow; void dinic() {while(bfs())mxflow+=dfs(S,inf);} int main() { n=read();m=read(); register int i,u,v,a,b,c,sum=0; for(i=2;i<n;++i){a=read();add(S,i,a);sum+=a;} for(i=2;i<n;++i){b=read();add(i,T,b);sum+=b;} add(S,1,inf);add(n,T,inf); tot=n; while(m--) { u=read();v=read();a=read();b=read();c=read(); add(S,++tot,a);add(tot,u,inf);add(tot,v,inf); add(++tot,T,b);add(u,tot,inf);add(v,tot,inf); readd(u,v,c);readd(v,u,c); sum+=a+b; } dinic(); print(sum-mxflow);puts(""); return 0; } /* 3 3 8 9 1 2 2 6 2 2 3 8 5 7 1 3 9 4 1 11 */