1. 程式人生 > >BZOJ3511: 土地劃分(最小割)

BZOJ3511: 土地劃分(最小割)

中一 設計 -s 擔心 32位 style font led %d

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 3
8
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位帶符號整數類型的表示範圍

解題思路:

二者必取其一,這個很有最小割的意思,所以相當於將A國是源點,B國為匯點

對於一個點$P_i$,設其分到A國的價值為$V_{ai}$,分到B國的價值為$V_{bi}$。

取A則無法取B,這就是最小割模型了。

那麽從源點連向$P_{i}$一條有向邊,容量為$V_{ai}$,那麽從$P_i$向匯點一條有向邊,容量為$V_{bi}$,

這樣點的二選一就實現了,只需要用$\sum{V_{ai}+V_{bi}}$減去最小割就可以啦。

下面是邊的三選一:(設一條邊連A國城市貢獻為$C_{ai}$,連B國城市貢獻為$C_{bi}$,連接兩個國家點懲罰為$C_{ci}$)

兩個點若都選A,那麽就需要割去這條邊連接B國兩個城市點貢獻。

選A相當於割去城市選B國點貢獻,那麽相當於在匯點端取消了流量。

那麽現在限制一下,要求其取消匯點端流量則必須取消這條邊流量。

那麽就相當於在原來兩個城市向匯點連邊處向匯點重新連邊。

由於兩個點都必須限制,那麽相當於在兩個點都向匯點連$\frac{C_{bi}}{2}$的邊。

同理從源點連向邊的兩端點$\frac{C_{ai}}{2}$的邊。

所以在答案上加上$\sum{C_{ai}+C_{bi}}$最後減去最小割。

考慮懲罰條件。

此時為邊的兩端一個割源,一個割匯。

此時為了保證出現割,保留與匯點連邊端必須斷開所有與源點連邊。

所以此時最小割中一定存在$\frac{C_{ai}}{2}$,也就是這條邊存在時與源點的附加邊。

同理,最小割中也存在$\frac{C_{bi}}{2}$,這樣割下來的代價為$\frac{C_{bi}}{2}+\frac{C_{ai}}{2}$

但是我們期望其扣除的代價為$C_{ai}+C_{bi}+C_{ci}$,這就要求我們同時要割下一條代價為$\frac{C_{bi}}{2}+\frac{C_{ai}}{2}+C_{ci}$的邊。

可是這條邊應該加在哪裏呢。

考慮什麽樣的邊一定被割掉,一定是當前存在的與源點連邊的點連向一個與匯點有流量的點。

那麽就是在當前邊兩端對應的點間加一雙向邊,邊權為$\frac{C_{bi}}{2}+\frac{C_{ai}}{2}+C_{ci}$。

證明這樣做的可行性。

因為當兩端選同一個國家時,中間的流量不會流向匯或不會與源有流量。

所以這條附加邊在兩端選同一國家時是不會存在流量的,更不會被割去。

所以建圖就是這樣了。

因為有系數$\frac{1}{2}$的存在,將所有邊權*2,最後/2,可以證明最後一定是整除的,沒有必要擔心。

全圖最小割就好了。

代碼:

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 const int oo=0x3f3f3f3f;
  6 struct pnt{
  7     int hd;
  8     int lyr;
  9     int now;
 10 }p[100000];
 11 struct ent{
 12     int twd;
 13     int lst;
 14     int vls;
 15 }e[1000000];
 16 int cnt;
 17 int n,m;
 18 int s,t;
 19 std::queue<int>Q;
 20 void ade(int f,int t,int v)
 21 {
 22     cnt++;
 23     e[cnt].twd=t;
 24     e[cnt].vls=v;
 25     e[cnt].lst=p[f].hd;
 26     p[f].hd=cnt;
 27     return ;
 28 }
 29 bool Bfs(void)
 30 {
 31     while(!Q.empty())
 32         Q.pop();
 33     for(int i=1;i<=t;i++)
 34         p[i].lyr=0;
 35     p[s].lyr=1;
 36     Q.push(s);
 37     while(!Q.empty())
 38     {
 39         int x=Q.front();
 40         Q.pop();
 41         for(int i=p[x].hd;i;i=e[i].lst)
 42         {
 43             int to=e[i].twd;
 44             if(p[to].lyr==0&&e[i].vls>0)
 45             {
 46                 p[to].lyr=p[x].lyr+1;
 47                 if(to==t)
 48                     return true;
 49                 Q.push(to);
 50             }
 51         }
 52     }
 53     return false;
 54 }
 55 int Dfs(int x,int fll)
 56 {
 57     if(x==t)
 58         return fll;
 59     for(int& i=p[x].now;i;i=e[i].lst)
 60     {
 61         int to=e[i].twd;
 62         if(p[to].lyr==p[x].lyr+1&&e[i].vls>0)
 63         {
 64             int ans=Dfs(to,std::min(fll,e[i].vls));
 65             if(ans>0)
 66             {
 67                 e[i].vls-=ans;
 68                 e[((i-1)^1)+1].vls+=ans;
 69                 return ans;
 70             }
 71         }
 72     }
 73     return 0;
 74 }
 75 int Dinic(void)
 76 {
 77     int ans=0;
 78     while(Bfs())
 79     {
 80         for(int i=1;i<=t;i++)
 81             p[i].now=p[i].hd;
 82         int dlt;
 83         while(dlt=Dfs(s,oo))
 84             ans+=dlt;
 85     }
 86     return ans;
 87 }
 88 int main()
 89 {
 90 //    freopen("a.in","r",stdin);
 91     scanf("%d%d",&n,&m);
 92     s=n+1;
 93     t=s+1;
 94     int ans=0;
 95     ade(s,1,oo);
 96     ade(1,s,0);
 97     ade(n,t,oo);
 98     ade(t,n,0);
 99     for(int i=2;i<=n-1;i++)
100     {
101         int x;
102         scanf("%d",&x);
103         x<<=1;
104         ade(s,i,x);
105         ade(i,s,0);
106         ans+=x;
107     }
108     for(int i=2;i<=n-1;i++)
109     {
110         int x;
111         scanf("%d",&x);
112         x<<=1;
113         ade(i,t,x);
114         ade(t,i,0);
115         ans+=x;
116     }
117     for(int i=1;i<=m;i++)
118     {
119         int x,y,a,b,c;
120         scanf("%d%d%d%d%d",&x,&y,&a,&b,&c);
121         ans+=a+b+a+b;
122         ade(s,x,a);
123         ade(x,s,0);
124         ade(s,y,a);
125         ade(y,s,0);
126         ade(x,t,b);
127         ade(t,x,0);
128         ade(y,t,b);
129         ade(t,y,0);
130         ade(x,y,a+b+c+c);
131         ade(y,x,a+b+c+c);
132     }
133     ans=(ans-Dinic())>>1;
134     printf("%d\n",ans);
135     return 0;
136 }

BZOJ3511: 土地劃分(最小割)