POJ-2594 Treasure Exploration
阿新 • • 發佈:2018-11-02
最小路徑覆蓋問題, 最小路徑覆蓋 = |V| - 最大匹配數
但是有一個問題,如果路徑可以相交,需要經過處理:如何處理
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; typedef long long ll; const int N=1000+10; const int M=3e5+10; const int INF=0x7f7f7f7f; struct Edge { int to,nxt; }edge[M]; int tot,first[N]; void addedge(int u,int v) { edge[tot].to=v; edge[tot].nxt=first[u]; first[u]=tot++; } void init() { tot=0; memset(first,-1,sizeof(first)); } int uN,dis; int Mx[N],My[N]; int dx[N],dy[N]; bool used[N]; bool SearchP() { queue<int> q; memset(dx,-1,sizeof(dx)); memset(dy,-1,sizeof(dy)); for(int i=1;i<=uN;i++) if(Mx[i]==-1) { q.push(i); dx[i]=0; } dis=INF; while(!q.empty()) { int u=q.front(); q.pop(); if(dx[u]>dis) break; for(int i=first[u];i!=-1;i=edge[i].nxt) { int v=edge[i].to; if(dy[v]==-1) { dy[v]=dx[u]+1; if(My[v]==-1) dis=dy[v]; else { dx[My[v]]=dy[v]+1; q.push(My[v]); } } } } return dis!=INF; } bool dfs(int u) { for(int i=first[u];i!=-1;i=edge[i].nxt) { int v=edge[i].to; if(!used[v]&&dy[v]==dx[u]+1) { used[v]=true; if(My[v]!=-1&&dy[v]==dis) continue; if(My[v]==-1||dfs(My[v])) { My[v]=u; Mx[u]=v; return true; } } } return false; } int MaxMatch() { int res=0; memset(Mx,-1,sizeof(Mx)); memset(My,-1,sizeof(My)); while(SearchP()) { memset(used,false,sizeof(used)); for(int i=1;i<=uN;i++) if(Mx[i]==-1&&dfs(i)) res++; } return res; } bool g[510][510]; int main() { int n,m,a,b; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; uN=n; init(); memset(g,false,sizeof(g)); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); g[a][b]=true; } for(int i=1;i<=n;i++) //按理說floyd第一個迴圈應該是k,我這裡寫錯了,但這道題能過,可能是沒有環的原因 for(int j=1;j<=n;j++) { if(i==j) continue; for(int k=1;k<=n;k++) if(g[i][k]&&g[k][j]) g[i][j]=true; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(g[i][j]) addedge(i,j+n); printf("%d\n",n-MaxMatch()); } return 0; }