http://acm.hdu.edu.cn/showproblem.php?pid=2686
http://acm.hdu.edu.cn/showproblem.php?pid=3376
首先贴上HDU上面两道Matrix,3376是2686的将强版本,3376的数据真是大的变态,数组开小了,白白送去了好几次wa,狂汗。。。。
题意:给定一个矩阵,从矩阵的左上角走到右下角然后从右下角走到左上角,能到得到最大max,每次不能走同样的路线。
既然是从头到尾,然后再从尾到头,那么我们可以转化下,都是从头到尾是一样的,两次的路线不是一样就可以了。显然到这里我们不男想到有最小费用最大流,但是关键是怎么建图:
建立源点s和汇点t那是 不必多说的,那么就是在矩阵里面是怎么的连线才是正确的,我们考察下,若就以点from - from+1,和from - from+n的话,画下图就在的我们并不能保证结果的正确性,所以我们这里要拆点,把每一个点[i][j],from拆成from,from+n*n,两点之间连一条线,流量为1,费用为da[i][j],然后我在给他们两个点脸一条边流量费Inf,费用为0,然后从from+n*n点向他的两个相邻方格连边。用s向1连费用为0,流量为2的边,2*n*n 向t连同样的的边。下面3376的代码。。。。。。
代码:
#include<stdio.h> #include<string.h> const int N = 2*360000+10 , Inf = 1<<30 ; int n,k,en,s,t,val[601][601],indx[N],road[N],pre[N],visit[N],d[N],q[10000001]; struct Node { int vdx,flow,cost,next; }Edge[40001000]; void add(int from,int to,int cost,int flow) { Edge[en].vdx = to ; Edge[en].flow= flow ; Edge[en].cost= cost ; Edge[en].next= indx[from] ; indx[from] = en ; en++ ; Edge[en].vdx = from ; Edge[en].flow= 0 ; Edge[en].cost= - cost ; Edge[en].next= indx[to] ; indx[to] = en ; en++ ; } bool spfa() { memset(visit,0,sizeof(visit)); memset(d,-1,sizeof(d)); visit[s]=1,d[s]=0; int head = 0 , tail = 0 ; q[tail++] = s ; while(head<tail) { int cur = q[head] ; head ++ ; visit[cur]=0; int next=indx[cur]; while(next!=-1) { if(Edge[next].flow>0&&d[Edge[next].vdx]<d[cur]+Edge[next].cost) { d[Edge[next].vdx] = d[cur]+Edge[next].cost ; pre[Edge[next].vdx] = cur ; road[Edge[next].vdx]= next; if(0==visit[Edge[next].vdx]) { visit[Edge[next].vdx] = 1 ; q[tail++] = Edge[next].vdx ; } } next=Edge[next].next; } } if(d[t]==-1) return false ; return true ; } int maxflow; void argue() { int minflow=1; for(int v=t;v!=s;v=pre[v]) { maxflow += minflow*Edge[road[v]].cost; Edge[road[v]].flow -= minflow ; Edge[road[v]^1].flow +=minflow ; } } int readT() { char c;int ret; while(c=getchar(),c<'0'||c>'9'); ret=c-'0'; while(c=getchar(),c>='0'&&c<='9')ret=ret*10+c-'0'; return ret; } int main() { while(scanf("%d",&n)!=EOF) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) val[i][j] = readT() ; en=0; s=2*n*n+1,t=s+1 ; int num=n*n+1; memset(indx,-1,sizeof(indx)); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { int x=i*n+j; add(x,x+num,val[i][j],1); add(x,x+num,0,Inf); if(i+1<n) add(x+num,x+n,0,Inf); if(j+1<n) add(x+num,x+1,0,Inf); } } add(s,0,0,2); add(n*n-1+num,t,0,2); maxflow=0; while(spfa()) argue(); printf("%d/n",maxflow); } return 0 ; }
http://acm.pku.edu.cn/JudgeOnline/problem?id=3422
这是HDU两道的加强版,把路径推广到了K跳而已。。。