一个写了2天的题目。。 都快写吐了。。 首先是构图的方法上 。。 开始想了各种构图的方法 都没有想对。。
最开始用floyd 然后跑了一遍最短路径, 求spath[i][t] == spath[j][t] + path[i][j] 的路 表示这条路是i到t最短路所用到的路。。
但是wa了。。 后来就开始到网上找 发现得用spath[s][t] = spath[s][i] + path[i][j] + spath[j][t] 来枚举 然后加入到网络流的网络中。。
但是还是各种wa 后来发现自己的网络流模板的汇点必须是最后的一个点。。 以后做gap优化的时候 是用最后一个点来标记路径的 应该改一下就可以改变汇点了
然后还是没有对。。 不知道是哪里错了 开始重写 重写了一遍交上去还是wa了 。。 就开始找别人的程序 自己生成数据 开始一个一个地对。。
发现是t0 == 0 和s0 == n-1的时候没有考虑,不过不考虑的话 交换邻接矩阵的时候就不对了。。
再交上去就对了 一共大约交了 20 多次 终于ac 泪奔了。。 自己弱的不行了。。
#include <cstdio>
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
const int MAXN=2000;
using namespace std;
const int inf = 0x7ffffff;
const int s = 0;
int path[MAXN][MAXN];
int spath[MAXN][MAXN];
struct edge{
int v,next,w;
}edge[20005];
int head[2*MAXN],cnt;//for sap
void addedge(int u, int v, int w)
{
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
edge[cnt].v = u;
edge[cnt].w = 0;
edge[cnt].next = head[v];
head[v] = cnt++;
}
int sap(int t)
{
//cout << "here" << endl;
int pre[2*MAXN],cur[2*MAXN],dis[2*MAXN],gap[2*MAXN]; //gap标记断层
int flow = 0 , aug = inf ,u;
bool flag;
for (int i = 0 ; i <= t ; ++i)
{
cur[i] = head[i];
gap[i] = dis[i] = 0;
}
gap[s] = t+1;
u = pre[s] = s;
while (dis[s] <= t)
{
flag = 0 ;
for (int &j = cur[u] ; ~j ; j = edge[j].next)
{
int v = edge[j].v;
if (edge[j].w > 0 && dis[u] == dis[v]+1)
{
flag = 1;
if( edge[j].w < aug )aug = edge[j].w;
pre[v] = u;
u = v;
if (u == t)
{
flow += aug;
while (u != s)
{
u = pre[u];
edge[cur[u]].w -= aug;
edge[cur[u]^1].w += aug;
}
aug = inf;
}
break;
}
}
if ( flag )continue ;
int mindis = t+1;
for (int j = head[u]; ~j ; j = edge[j].next)
{
int v = edge[j].v;
if (edge[j].w > 0 && dis[v] < mindis)
{
mindis = dis[v];
cur[u] = j;
}
}
if(--gap[dis[u]] == 0)break;
gap[ dis[u] = mindis+1 ]++;
u = pre[u];
}
return flow;
}
void swap ( int &a , int & b)
{
int temp = a;
a = b;
b = temp;
}
void init ()
{
memset (head , -1 , sizeof(head));
cnt=0;
}
void floyd ( int n )
{
for ( int k = 0 ; k < n ; k ++ )
for ( int i = 0 ; i < n; i ++)
for ( int j = 0 ; j < n; j ++ )
{
spath[i][j] = min ( spath[i][j] , spath[i][k] + spath[k][j] );
}
}
int main()
{
int n;
//freopen("out.txt" , "r" , stdin );
//freopen("myrun.txt" , "w" ,stdout );
while ( cin >> n )
{
init();
for ( int i =0 ; i < n; i ++ )
for ( int j = 0 ; j < n; j ++ )
{
cin >> path[i][j];
if ( path[i][j] == -1 )
path[i][j] = inf;
if ( i == j )
path[i][j] = 0;
}
int s0 , t0 ;
cin >> s0 >> t0;
if ( t0 == 0 )
{
for ( int i = 0 ; i < n; i ++ )
swap( path[i][t0] , path[i][s0] );
for ( int i = 0 ; i < n ; i ++ )
swap( path[s0][i] , path[t0][i] );
t0 = s0;
s0 = 0;
if ( t0 != 0 )
{
for ( int i = 0 ; i < n; i ++ )
swap ( path[i][t0] , path[i][n-1] );
for ( int i = 0 ; i < n; i ++ )
swap ( path[t0][i] , path[n-1][i]);
}
}
if ( s0 == n-1 )
{
for ( int i = 0 ; i < n; i ++ )
swap( path[i][t0] , path[i][s0] );
for ( int i = 0 ; i < n ; i ++ )
swap( path[s0][i] , path[t0][i] );
s0 = t0;
t0 = n-1 ;
if ( s0 != 0 )
{
for ( int i = 0 ; i < n; i ++ )
swap( path[i][0] , path[i][s0] );
for ( int i = 0 ; i < n ; i ++ )
swap( path[0][i] , path[s0][i] );
}
}
else
{
if ( s0 != 0 )
{
for ( int i = 0 ; i < n; i ++ )
swap( path[i][0] , path[i][s0] );
for ( int i = 0 ; i < n ; i ++ )
swap( path[0][i] , path[s0][i] );
}
if ( t0 != 0 )
{
for ( int i = 0 ; i < n; i ++ )
swap ( path[i][t0] , path[i][n-1] );
for ( int i = 0 ; i < n; i ++ )
swap ( path[t0][i] , path[n-1][i]);
}
}
for ( int i = 0 ; i < n; i ++ )
for ( int j = 0; j < n; j ++ )
spath[i][j] = path[i][j];
floyd ( n );
// for ( int i = 0 ; i < n ; i ++ )
// for ( int j = 0 ; j < n ; j++ )
// cout << "spath[" << i << "][" << j << "] = " << spath[i][j] << endl;
//cout << "here" << endl;
//cout << spath[0][t0] << endl;
//t0 = n-1;
for ( int i = 0 ; i < n; i ++)
for ( int j = 0 ; j < n; j ++)
if ( spath[0][n-1] == spath[0][i] + path[i][j] + spath[j][n-1] && i != j && spath[0][i] < inf && spath[j][n-1] < inf && path[i][j] < inf )
{
// cout << "here" << endl;
addedge ( i , j , 1 );
//cout << i << " " << j << endl;
}
//cout << "here" << endl;
//cout << t0 << endl;
if ( s0 == t0 )
cout << "inf" << endl;
else
cout << sap( n-1 ) << endl;
}
return 0;
}