JZOJ 3597. 【CQOI2014】危桥
Description
Alice和Bob居住在一個由N座島嶼組成的國家,島嶼被編號為0到N-1。某些島嶼之間有橋相連,橋上的道路是雙向的,但一次只能供一人通行。其中一些橋由于年久失修成為危橋,最多只能通行兩次。
Alice希望在島嶼a1和a2之間往返an次(從a1到a2再從a2到a1算一次往返)。同時,Bob希望在島嶼b1和b2之間往返bn次。這個過程中,所有危橋最多通行兩次,其余的橋可以無限次通行。請問Alice和Bob能完成他們的愿望嗎?
Input
本題有多組測試數據。
每組數據第一行包含7個空格隔開的整數,分別為N、a1、a2、an、b1、b2、bn。
接下來是一個N行N列的對稱矩陣,由大寫字母組成。矩陣的i行j列描述編號i-1和j-1的島嶼間的連接情況,若為“O”則表示有危橋相連;為“N”表示有普通的橋相連;為“X”表示沒有橋相連。
Output
對于每組測試數據輸出一行,如果他們都能完成愿望輸出“Yes”,否則輸出“No”。
Sample Input
4 0 1 1 2 3 1
XOXX
OXOX
XOXO
XXOX
4 0 2 1 1 3 2
XNXO
NXOX
XOXO
OXOX
Sample Output
Yes
No
Data Constraint
4<=N<=50
0<=a1,a2,b1,b2<=N-1
1<=an,bn<=50
Solution
這就是最小割模型了,直接上網絡流啊!
建超級源 S 和超級匯 T 。
S 向 a1 、b1 連一條容量為正無窮的邊,表示不能割斷。
a2 、b2 向 T 連一條容量為正無窮的邊,表示也不能割斷。
如果島 i 到島 j 有一條普通橋,則連一條容量為正無窮的邊,表示還是不能割斷。
如果島 i 到島 j 有一條危橋,則連一條容量為 1 的邊,表示做一次往返就會割掉。
那么跑一次得出的的最大流就是能進行的往返次數了!
但是由于是雙源雙匯,只跑一次可能會發生串流(即跑偏)。
于是我們調轉 b1 、b2 (本質不變),再跑一遍看滿不滿足即可。
同時還要單獨判 a 和 b ,共判四次(避免特殊情況)。
時間復雜度就是網絡流的時間復雜度。
Code
#include<cstdio> #include<cstring> using namespace std; const int N=55,M=N*N<<1,inf=1e9; int n,a1,a2,an,b1,b2,bn; int tot,ans,num,s,t; int first[N],next[M],en[M],w[M]; int a[N][N],dis[N],gap[N],cur[N]; inline void ins(int x,int y,int z) {next[++tot]=first[x];first[x]=tot;en[tot]=y;w[tot]=z; } inline void insert(int x,int y,int z) {ins(x,y,z),ins(y,x,0); } inline int min(int x,int y) {return x<y?x:y; } int dfs(int x,int y) {if(x==t) return y;int use=0;for(int i=cur[x];i;i=next[i])if(w[i] && dis[x]==dis[en[i]]+1){cur[x]=i;int num=dfs(en[i],min(w[i],y-use));w[i]-=num,w[i^1]+=num,use+=num;if(use==y || dis[s]>num) return use;}cur[x]=first[x];if(!--gap[dis[x]]) dis[s]=num+1;gap[++dis[x]]++;return use; } int main() {while(~scanf("%d",&n)){scanf("%d%d%d",&a1,&a2,&an);scanf("%d%d%d",&b1,&b2,&bn);a1++,a2++,b1++,b2++;for(int i=1;i<=n;i++){int j=0;char ch=getchar();while(ch^'O' && ch^'N' && ch^'X') ch=getchar();while(ch=='O' || ch=='N' || ch=='X'){j++;if(ch=='O') a[i][j]=1; elseif(ch=='N') a[i][j]=inf; else a[i][j]=0;ch=getchar();}}s=a1,t=a2,ans=0,tot=1,num=n;memset(first,0,sizeof(first));memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i^j && a[i][j]) insert(i,j,a[i][j]);for(int i=1;i<=num;i++) cur[i]=first[i];tot>>=1,gap[0]=num;while(dis[s]<=num) ans+=dfs(s,inf);if(ans<an){puts("No");continue;}s=b1,t=b2,ans=0,tot=1,num=n;memset(first,0,sizeof(first));memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i^j && a[i][j]) insert(i,j,a[i][j]);for(int i=1;i<=n;i++) cur[i]=first[i];tot>>=1,gap[0]=num;while(dis[s]<=num) ans+=dfs(s,inf);if(ans<bn){puts("No");continue;}s=n+1,t=n+2,ans=0,tot=1,num=n+2;memset(first,0,sizeof(first));memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i^j && a[i][j]) insert(i,j,a[i][j]);insert(s,a1,inf),insert(s,b1,inf);insert(a2,t,inf),insert(b2,t,inf);for(int i=1;i<=t;i++) cur[i]=first[i];tot>>=1,gap[0]=num;while(dis[s]<=num) ans+=dfs(s,inf);if(ans<an+bn){puts("No");continue;}s=n+1,t=n+2,ans=0,tot=1,num=n+2;memset(first,0,sizeof(first));memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i^j && a[i][j]) insert(i,j,a[i][j]);insert(s,a1,inf),insert(s,b2,inf);insert(a2,t,inf),insert(b1,t,inf);for(int i=1;i<=t;i++) cur[i]=first[i];tot>>=1,gap[0]=num;while(dis[s]<=num) ans+=dfs(s,inf);puts(ans<an+bn?"No":"Yes");}return 0; }總結
以上是生活随笔為你收集整理的JZOJ 3597. 【CQOI2014】危桥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 3596. 【CQOI2014
- 下一篇: JZOJ 4366. 【GDKOI201