Treasure Exploration poj2594(传递闭包+最少路径覆盖)
Sample Input
1 0 2 1 1 2 2 0 0 0
Sample Output
1 1 2
题意:一副地图,单向边,但没有环,问最少有几条路径能覆盖全图(一条路径不能重复点,多条路径可以交叉)。
思路:先跑floyd闭环,找出那些点可达,然后用最小路径覆盖找到那些边,最后答案是总点-cnt。
补题参考链接:https://blog.csdn.net/guagua_de_xiaohai/article/details/86564298
代码:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #pragma GCC optimize(2) 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 #include<cstring> 7 #include<queue> 8 #include<set> 9 #include<cmath> 10 #include<string> 11 #include<map> 12 #include<vector> 13 #include<ctime> 14 #include<stack> 15 using namespace std; 16 #define mm(a,b) memset(a,b,sizeof(a)) 17 typedef long long ll; 18 const long long mod = 1e9+7; 19 const int maxn = 5e2+10; 20 const int inf = 0x3f3f3f3f; 21 int un,vn; 22 int g[maxn][maxn]; 23 int linker[maxn]; 24 int used[maxn]; 25 int n,mm; 26 27 bool dfs(int u) 28 { 29 for(int v=1;v<=vn;v++) 30 { 31 if(g[u][v]&&!used[v]) 32 { 33 used[v]=true; 34 if(linker[v]==-1||dfs(linker[v])) 35 { 36 linker[v]=u; 37 return true; 38 } 39 } 40 } 41 return false; 42 } 43 44 int hungary() 45 { 46 int res=0; 47 mm(linker,-1); 48 for(int u=1;u<=un;u++) 49 { 50 mm(used,false); 51 if(dfs(u)) res++; 52 } 53 return res; 54 } 55 int main() 56 { 57 while(cin>>n>>mm&&n+mm) 58 { 59 int u,v; 60 mm(g,0); 61 while(mm--) 62 { 63 scanf("%d %d",&u,&v); 64 g[u][v]=1; 65 } 66 un=vn=n; 67 for(int k=1;k<=n;k++) 68 { 69 for(int i=1;i<=n;i++) 70 { 71 for(int j=1;j<=n;j++) 72 { 73 if(g[i][k]&&g[k][j]) 74 g[i][j]=1; 75 } 76 } 77 } 78 int ans=hungary(); 79 ans=n-ans; 80 printf("%d\n",ans); 81 } 82 return 0; 83 }