1. 程式人生 > >解題:BJOI 2006 狼抓兔子

解題:BJOI 2006 狼抓兔子

題面

可以看出來是最小割,然後你就去求最大流了

這麼大的範圍就是讓你用網路流卡的?咋想的啊=。=???

建議還是老老實實用 平面圖最小割等於其對偶圖最短路 這個東西來做吧,雖然這個東西跑的也挺慢的,最後一個點跑了$2s$

對偶圖就是被邊分割出來的每個區域當成一個點,然後兩個區域有公共邊就連邊,起點和終點的問題就在源匯點中間連一條邊然後就能分出來了

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cctype> 
 4 #include<cstring>
 5 #include<algorithm>
 6
using namespace std; 7 const int N=2000005,M=6000005; 8 struct a{int node,dist;}; 9 bool operator < (a x,a y) 10 { 11 return x.dist>y.dist; 12 } 13 priority_queue<a> hp; 14 int p[N],noww[2*M],goal[2*M],val[2*M],dis[N],vis[N]; 15 int n,m,rd,st,ed,bs,t1,t2,cnt; 16 void Read(int &x) 17 { 18
x=0; char ch=getchar(); 19 while(!isdigit(ch)) 20 ch=getchar(); 21 while(isdigit(ch)) 22 x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); 23 } 24 void Link(int f,int t,int v) 25 { 26 noww[++cnt]=p[f],p[f]=cnt; 27 goal[cnt]=t,val[cnt]=v; 28 } 29 int ID(int a,int b,int
c) 30 { 31 if(a>n||!b) return st; 32 if(!a||b>m) return ed; 33 return (a-1)*m+b+c*n*m; 34 } 35 void Dijkstra() 36 { 37 memset(dis,0x3f,sizeof dis); 38 dis[st]=0,hp.push((a){st,0}); 39 while(!hp.empty()) 40 { 41 a tt=hp.top(); hp.pop(); int tn=tt.node; 42 if(vis[tn]) continue; vis[tn]=true; 43 for(int i=p[tn];i;i=noww[i]) 44 if(dis[goal[i]]>dis[tn]+val[i]) 45 { 46 dis[goal[i]]=dis[tn]+val[i]; 47 hp.push((a){goal[i],dis[goal[i]]}); 48 } 49 } 50 } 51 int main() 52 { 53 register int i,j; 54 Read(n),Read(m); 55 n--,m--,st=2*n*m+1,ed=st+1; 56 for(i=1;i<=n+1;i++) 57 for(j=1;j<=m;j++) 58 { 59 Read(rd),t1=ID(i,j,1),t2=ID(i-1,j,0); 60 Link(t1,t2,rd),Link(t2,t1,rd); 61 } 62 for(i=1;i<=n;i++) 63 for(j=1;j<=m+1;j++) 64 { 65 Read(rd),t1=ID(i,j,0),t2=ID(i,j-1,1); 66 Link(t1,t2,rd),Link(t2,t1,rd); 67 } 68 for(i=1;i<=n;i++) 69 for(j=1;j<=m;j++) 70 { 71 Read(rd),t1=ID(i,j,0),t2=ID(i,j,1); 72 Link(t1,t2,rd),Link(t2,t1,rd); 73 } 74 Dijkstra(); printf("%d",dis[ed]); 75 return 0; 76 }
View Code