POJ 3422 Kaka's Matrix Travels(最小费用最大流+拆点)

题目链接

关键在于建图,昨天做的的时候直接想错了。放了放,在路上和gyx讨论了一下,他说是不是拆点,我一想真是啊。。。

然后想了想建图的细节。。。今天写了程序,居然把电脑给写挂了。。第一次啊,可见程序写的多不靠谱啊。。

把一个点拆成两个点,这两个点之间的流量为1,费用为权值,这条边的起点和终点都可以连接下个位置的起点。

为了控制流量,多加了k个点,这多出来的k个点,到终点的流量为1,来控制最终的流量。剩下的就是模版了,改了一下求最大。

这样建图效率不是很高,想会不会超时。。。果真TLE了,不过数组开小了,开大之后,水过400+ms。。。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <queue>
  5 using namespace std;
  6 #define INF 0x7fffffff
  7 
  8 int p[51][51];
  9 
 10 int low[6001],path[6001];
 11 int first[6001],in[6001],dis[6001];
 12 int str,end,t;
 13 struct node
 14 {
 15     int u,v,w,cost,re,next;
 16 }edge[900001];
 17 int ans;
 18 void CL()
 19 {
 20     t = 1;
 21     memset(first,-1,sizeof(first));
 22 }
 23 void add(int u,int v,int w,int cost)
 24 {
 25     edge[t].u = u;
 26     edge[t].v = v;
 27     edge[t].w = w;
 28     edge[t].cost = cost;
 29     edge[t].re = t+1;
 30     edge[t].next = first[u];
 31     first[u] = t ++;
 32 
 33     edge[t].u = v;
 34     edge[t].v = u;
 35     edge[t].w = 0;
 36     edge[t].cost = -cost;
 37     edge[t].re = t-1;
 38     edge[t].next = first[v];
 39     first[v] = t ++;
 40 }
 41 int bfs()
 42 {
 43     int u,i,v;
 44     memset(path,-1,sizeof(path));
 45     for(i = 0;i <= end;i ++)
 46     {
 47         dis[i] = -INF;
 48         in[i] = 0;
 49     }
 50     queue<int>que;
 51     que.push(str);
 52     dis[str] = 0;
 53     in[str] = 1;
 54     low[str] = INF;
 55     while(!que.empty())
 56     {
 57         u = que.front();
 58         in[u] = 0;
 59         que.pop();
 60         for(i = first[u];i != -1;i = edge[i].next)
 61         {
 62             v = edge[i].v;
 63             if(edge[i].w&&dis[v] < dis[u]+edge[i].cost)
 64             {
 65                 dis[v] = dis[u] + edge[i].cost;
 66                 path[v] = i;
 67                 low[v] = low[u] < edge[i].w ? low[u]:edge[i].w;
 68                 if(!in[v])
 69                 {
 70                     que.push(v);
 71                     in[v] = 1;
 72                 }
 73             }
 74         }
 75     }
 76     if(path[end] == -1)
 77     return -1;
 78     else
 79     return low[end];
 80 
 81 }
 82 void mcmf()
 83 {
 84     int res,temp,now;
 85     while((res = bfs()) != -1)
 86     {
 87         now = end;
 88         while(now != str)
 89         {
 90             temp = path[now];
 91             edge[temp].w -= res;
 92             edge[edge[temp].re].w += res;
 93             ans += res*edge[temp].cost;
 94             now = edge[temp].u;
 95         }
 96     }
 97 }
 98 int main()
 99 {
100     int n,i,j,k;
101     int x,y;
102     ans = 0;
103     CL();
104     scanf("%d %d",&n,&k);
105     for(i = 1;i <= n;i ++)
106     {
107         for(j = 1;j <= n;j ++)
108         scanf("%d",&p[i][j]);
109     }
110     str = 0;
111     end = 2*n*n + k + 1;
112     add(str,1,INF,0);
113     for(i = 1;i <= n;i ++)
114     {
115         for(j = 1;j <= n;j ++)
116         {
117             x = (i-1)*n + j;
118             y = x + n*n;
119             add(x,y,1,p[i][j]);
120             if(i + 1 <= n)
121             {
122                 add(x,x+n,INF,0);
123                 add(y,x+n,INF,0);
124             }
125             if(j + 1 <= n)
126             {
127                 add(x,x+1,INF,0);
128                 add(y,x+1,INF,0);
129             }
130         }
131     }
132     for(i = 1;i <= k;i ++)
133     {
134         add(x,2*n*n+i,INF,0);
135         add(y,2*n*n+i,INF,0);
136         add(2*n*n+i,end,1,0);
137     }
138     mcmf();
139     printf("%d\n",ans);
140     return 0;
141 }

 

 

 

posted @ 2013-02-27 11:21  Naix_x  阅读(247)  评论(0编辑  收藏  举报