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 }

 

 

 

你可能感兴趣的:(Matrix)