Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1665 Accepted Submission(s): 901
2 10 3 5 10 3 10 3 3 2 5 3 6 7 10 5 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9
28 46 80
从左上到右下在走回左上,每个点只能经过一次,问最大的权值和是多少
可以当做成从左上到右下走过两次,至于每个点只能走过一次,需要拆点,每个点i到对应的i点容量是1,使得该点只能走过一次。
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; #define maxn 3000 #define INF 0x3f3f3f3f struct node { int v , w , s ; int next ; } p[3000000]; int a[50][50] , head[maxn] , cnt ; int pre[maxn] , vis[maxn] , dis[maxn] ; queue <int> q ; void add(int u,int v,int w,int s) { p[cnt].v = v ; p[cnt].w = w ; p[cnt].s = s ; p[cnt].next = head[u] ; head[u] = cnt++ ; p[cnt].v = u ; p[cnt].w = 0 ; p[cnt].s = -s ; p[cnt].next = head[v] ; head[v] = cnt++ ; } int spfa(int s,int t) { int u , v , i ; memset(dis,INF,sizeof(dis)); dis[s] = 0 ; vis[s] = 1 ; pre[s] = pre[t] = -1 ; while( !q.empty() ) q.pop(); q.push(s) ; while( !q.empty() ) { u = q.front(); q.pop(); vis[u] = 0 ; for(i = head[u] ; i != -1 ; i = p[i].next) { v = p[i].v ; if( p[i].w && dis[v] > dis[u] + p[i].s ) { dis[v] = dis[u] + p[i].s ; pre[v] = i ; if( !vis[v] ) { vis[v] = 1 ; q.push(v) ; } } } } if( pre[t] == -1 ) return 0 ; return 1 ; } void f(int s,int t) { memset(pre,-1,sizeof(pre)); memset(vis,0,sizeof(vis)); int i , ans = 0 , min1 ; while( spfa(s,t) ) { min1 = INF ; for(i = pre[t] ; i != -1 ; i = pre[ p[i^1].v ]) if( p[i].w < min1 ) min1 = p[i].w ; for(i = pre[t] ; i != -1 ; i = pre[ p[i^1].v ]) { p[i].w -= min1 ; p[i^1].w += min1 ; ans += p[i].s ; } } printf("%d\n", -ans); } int main() { int i , j , n , b , temp; while(scanf("%d", &n)!=EOF) {/*和D相同,不过这一个题换成了每个点只能经过一次,要求从左上走到右下,再走回左上,可以认为是从左上走到右下两次 */ memset(head,-1,sizeof(head)); cnt = 0 ; temp = n*n ; for(i = 1 ; i <= n ; i++) for(j = 1 ; j <= n ; j++) { scanf("%d", &a[i][j]); b = (i-1)*n + j ; if(b == 1 || b == temp) add(b,b+temp,1,0);//源点和汇点会被走两次 add(b,b+temp,1,-a[i][j]);//拆点操作,使得每个点只会被经过一次。 } for(i = 1 ; i <= n ; i++) for(j = 1 ; j <= n ; j++) { b = (i-1)*n+j ; if(i > 1) add(b-n+temp,b,1,0); if(j > 1) add(b-1+temp,b,1,0); } add(0,1,2,0); add(2*n*n,2*n*n+1,2,0); f(0,2*n*n+1); } return 0; }