Link:Http://poj.org/problem? Id = 3422
Kaka
Question:KaKa's matrix journey involves an N * n matrix. Kaka will go from the upper left corner to the lower right corner. Each time he can only go right or down, Kaka can go K times through this matrix, each vertex has a num value. When Kaka comes here, he can get the num point. One vertex can only get the num value once. What is the maximum num value of Kaka after K times?
Ideas:In fact, I had no idea when I saw this question. In the graph theory book, I talked about the method of creating a graph, but I didn't explain why. I searched the solution Report on the Internet and Baidu posted two pages, the blogs I see are all about how to create a graph, but I didn't know why to do this .. I think I am really a weak scum. People can understand how to build a picture immediately. I still don't understand how to build a picture. If I can't find a description, I just want to think about it myself! It is not difficult to think about it myself. I understood why it is relatively simple to split the question. The following is what I wrote after thinking about it:
First of all, greed is definitely not feasible. The greedy idea is to obtain the largest sum value every time. If you do this only once, you also need to consider the situation that has passed through. Greedy can barely do it, DP is better. But now we have to go K times, and each trip will have an impact on the next step, because we can only go in two directions at a time, and we need to reasonably plan the K steps, my DP is weak. I don't know if DP can be implemented.
Follow the idea of network stream: K times, and each location has a value of num. It is not advisable to use num as the traffic because this value is the final answer, is to accumulate, and the traffic is the largest in the path, not accumulate.
So what is traffic? The K value can be regarded as the final largest stream. The Arc traffic of the Super source and super sink is K, which limits only K times, the entire route is counted as one traffic, and the total traffic is K.
So what is num used? Num becomes the limit in the network. When the maximum stream is the same as the maximum num value, it is actually the maximum minimum fee, but now it is not the minimum fee, but the maximum fee.
Now let's look at how to create a graph in the matrix. It's easy to think of every point connecting an arc to the right and bottom of it. You can choose the num value for this point, but the capacity is not good. Imagine that if the capacity is INF, Kaka can go K times each time with the highest total num value, because the matrix does not limit the number of visits, the limit is imposed only on the Super source sink, but the num value of a vertex can only be retrieved once. So the num value equals to a vertex is retrieved K times. Should the capacity be 1? No. If you set the value to 1, you can only get it once, but the problem comes with it: if there is a path between point A and point B, this path can only be taken once. This rule is not specified in the question, A point can be taken multiple times, but the value can only be taken once. The size of K is the same as that of INF, and cannot be obtained.
To solve the problem that one value can only be retrieved once, but one point can be taken multiple times, there is a widely spread method on the Internet:Split point.
After the split, the point becomes a' and A', and A' → a' indicates that the num value of the point is obtained. The capacity of this arc is 1 and the fee is num, connect an arc with the same endpoint, with the capacity INF and the fee of 0. This ensures that the value of one vertex is only taken once. Point B is split into B and B, and A and B are connected to B. The capacity is INF, it means that a point can be taken many times, which can solve the problem just now.
In fact, we should do a few more questions to think about splitting points.
Graph creation:As I mentioned in the previous section, the construction of graphs in the matrix is as mentioned above. There is no cost for the arc as long as the capacity is not smaller than K. In the upper left corner of the Super Source Vertex's ing matrix, the capacity is K and the cost is 0. in the lower right corner of the matrix, the vertex a' connects to the super sink vertex. The capacity is K and the cost is 0.
After understanding it, it took a long time to get the AC, because the DIST array initialization in spfa is small, and the program is in an endless loop.
Another point is that the ans I output are global variables. I defined an ans in the main function. The program preferentially uses local variables and outputs 0 infinitely .. I found out after debugging for a long time ..
#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 500100#define eps 1e-7#define INF 0x7FFFFFFF#define LLINF 0x7FFFFFFFFFFFFFFF#define seed 131#define mod 1000000007#define ll long long#define ull unsigned ll#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1struct node{ int u,v,w,cost,next;}edge[MAXN];int head[5200],dist[5200],pree[5200],vis[5200];int n,m,k,cnt,src,sink,ans,nn;int a[60][60];void add_edge(int a,int b,int c,int d){ edge[cnt].v = b; edge[cnt].w = c; edge[cnt].cost = d; edge[cnt].next = head[a]; head[a] = cnt++;}void build_graph(){ int i,j; cnt = 0; memset(head,-1,sizeof(head)); src = 0; sink = n * n * 2 + 1; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ int tt = (i-1)*n+j; add_edge(tt,tt+nn,1,-a[i][j]); add_edge(tt+nn,tt,0,a[i][j]); add_edge(tt,tt+nn,k,0); add_edge(tt+nn,tt,0,0); if(i+1<=n){ add_edge(tt+nn,tt+n,k,0); add_edge(tt+n,tt+nn,0,0); } if(j+1<=n){ add_edge(tt+nn,tt+1,k,0); add_edge(tt+1,tt+nn,0,0); } } } add_edge(src,1,k,0); add_edge(1,src,0,0); add_edge(nn*2,sink,k,0); add_edge(sink,nn*2,0,0);}bool spfa(){ int i,j; queue<int>q; q.push(src); memset(vis,0,sizeof(vis)); int lll = nn*2+5; for(i=0;i<=lll;i++) dist[i] = INF; dist[src] = 0; vis[src] = 1; while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = 0; for(i=head[u];i!=-1;i=edge[i].next){ if(edge[i].w!=0&&dist[u]+edge[i].cost<dist[edge[i].v]){ dist[edge[i].v] = dist[u] + edge[i].cost; pree[edge[i].v] = i; if(!vis[edge[i].v]){ vis[edge[i].v] = 1; q.push(edge[i].v); } } } } if(dist[sink]!=INF) return true; return false;}int augment(){ int i,j; int delta = INF; for(i=sink;i!=src;i=edge[j^1].v){ j = pree[i]; delta = min(delta,edge[j].w); } for(i=sink;i!=src;i=edge[j^1].v){ j = pree[i]; edge[j].w -= delta; edge[j^1].w += delta; ans += edge[j].cost; } return delta;}int main(){ int i,j; int b,c,d; ans = 0; scanf("%d%d",&n,&k); nn = n * n; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ scanf("%d",&a[i][j]); } } build_graph(); while(spfa()) augment(); printf("%d\n",-ans); return 0;}