题意:
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路
1:(x,y)<==>(x+1,y)
2:(x,y)<==>(x,y+1)
3:(x,y)<==>(x+1,y+1)
道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
Output
题解:
求平面图的最小割问题,直接求时间复杂度不允许,考虑把原图转换成对偶图,直接上dijkstra求最短路。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int maxn=2000010; const int inf=1e9; int N,M; int s,t; struct e { int from; int to; int next; int flow; }edge[maxn*4]; int head[maxn]; int tol; void addedge (int u,int v,int flow) { edge[tol].from=u; edge[tol].to=v; edge[tol].next=head[u]; edge[tol].flow=flow; head[u]=tol++; edge[tol].from=v; edge[tol].to=u; edge[tol].next=head[v]; edge[tol].flow=flow; head[v]=tol++; } struct node { int v,w; }cur,tail; bool operator < (node a,node b) { return a.w>b.w; } int d[maxn]; int visit[maxn]; void dijkstra (int s,int t) { for (int i=0;i<maxn;i++) d[i]=inf; memset(visit,0,sizeof(visit)); d[s]=0; priority_queue<node> q; cur.v=s; cur.w=0; q.push(cur); while (!q.empty()) { cur=q.top(); q.pop(); int x=cur.v; if (visit[x]) continue; visit[x]=1; for (int i=head[x];i!=-1;i=edge[i].next) { if (d[edge[i].to]>d[x]+edge[i].flow) { d[edge[i].to]=d[x]+edge[i].flow; tail.v=edge[i].to; tail.w=d[edge[i].to]; q.push(tail); } } } printf("%d ",d[t]); } int main () { while (~scanf("%d%d",&N,&M)) { memset(head,-1,sizeof(head)); tol=0; s=0; t=2*(N-1)*(M-1)+1; int x,y,cost; for (int i=1;i<=N;i++) { for (int j=1;j<M;j++) { scanf("%d",&cost); x=i==1?s:(2*(i-1)-1)*(M-1)+j; y=i==N?t:(2*(i-1))*(M-1)+j; addedge(x,y,cost); } } for (int i=1;i<N;i++) { for (int j=1;j<=M;j++) { scanf("%d",&cost); x=j==1?t:(2*(i-1))*(M-1)+j-1; y=j==M?s:(2*(i-1))*(M-1)+j-1+M; addedge(x,y,cost); } } for (int i=1;i<N;i++) { for (int j=1;j<M;j++) { scanf("%d",&cost); x=(2*(i-1))*(M-1)+j; y=(2*(i-1)+1)*(M-1)+j; addedge(x,y,cost); } } dijkstra(s,t); } return 0; }