POJ 2594

来源:互联网 发布:数据挖掘毕业设计 编辑:程序博客网 时间:2024/06/07 06:02

还是DAG上的最少路径覆盖,此题说有的点可以重复走,最后的选择结果,一个点所在路径的下一个点不管是怎么到达的,只要可达就可以。用二分匹配求最少路径覆盖,二分图中边的含义就是i下一个点可走j,所以建二分图时,只要两点可达就连边。floyd求是否可达。

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <cmath>#include <stack>#include <vector>#define LL long long#define myabs(x) ((x)>0?(x):(-(x)))using namespace std;const int inf=0x3f3f3f3f;const int maxn=500+10;int g[maxn][maxn];int vis[maxn],leftp[maxn];int n,m;int dfs(int u){int i;for(i=1;i<=n;i++){if(g[u][i]&&!vis[i]){vis[i]=1;if(leftp[i]==-1||dfs(leftp[i])){leftp[i]=u;return 1;}}}return 0;}int solve(){int i,sum=0;memset(leftp,-1,sizeof(leftp));for(i=1;i<=n;i++){memset(vis,0,sizeof(vis));if(dfs(i)) sum++;}return n-sum;}void floyd(){int i,j,k;               for(k=1;k<=n;k++)for(i=1;i<=n;i++)if (g[i][k])//这里优化一下速度明显提高很多{for(j=1;j<=n;j++)g[i][j]=g[i][j]||(g[i][k]&&g[k][j]);}}int main(){while(~scanf("%d%d",&n,&m)){if(!n&&!m) break; int i;int u,v;memset(g,0,sizeof(g));for(i=0;i<m;i++){scanf("%d%d",&u,&v);g[u][v]=1;}floyd();int j;int ans=solve();printf("%d\n",ans);}return 0;}