LiberOJ #6002. 「網絡流 24 題」最小路徑覆蓋
阿新 • • 發佈:2017-08-12
技術分享 記錄 -m lock onclick stat blog 自己 給定
#6002. 「網絡流 24 題」最小路徑覆蓋
內存限制:256 MiB時間限制:1000 ms標準輸入輸出 題目類型:傳統評測方式:Special Judge 上傳者: 匿名 提交提交記錄統計討論測試數據題目描述
給定有向圖 G=(V,E) G = (V, E)G=(V,E)。設 P PP 是 G GG 的一個簡單路(頂點不相交)的集合。如果 V VV 中每個頂點恰好在 P PP 的一條路上,則稱 P PP 是 G GG 的一個路徑覆蓋。P PP 中路徑可以從 V VV 的任何一個頂點開始,長度也是任意的,特別地,可以為 0 00。G GG 的最小路徑覆蓋是 G GG 的所含路徑條數最少的路徑覆蓋。
設計一個有效算法求一個有向無環圖 G GG 的最小路徑覆蓋。
輸入格式
第 1 11 行有 2 22 個正整數 n nn 和 m mm。n nn 是給定有向無環圖 G GG 的頂點數,m mm 是 G GG 的邊數。
接下來的 m mm 行,每行有 2 22 個正整數 u uu 和 v vv,表示一條有向邊 (i,j) (i, j)(i,j)。
輸出格式
從第 1 11 行開始,每行輸出一條路徑。
文件的最後一行是最少路徑數。
樣例
樣例輸入
11 12 1 2 1 3 1 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 11 10 11
樣例輸出
1 4 7 10 11
2 5 8
3 6 9
3
數據範圍與提示
1≤n≤200,1≤m≤6000 1 \leq n \leq 200, 1 \leq m \leq 60001≤n≤200,1≤m≤6000
題目鏈接:https://loj.ac/problem/6002
題意:輸出一個有向圖的點不重復的最小路徑覆蓋。
思路:點不重復的最小路徑覆蓋。最初始每個點都最為自己一個獨立的路徑,如果有一個匹配,那麽路徑-1,所以最小路徑覆蓋,點不重復的情況就是求最大匹配。
點可重復的最小路徑覆蓋也是使用匹配,只不過,需要增加一些邊,如果u可以到達匹配,則增加<u,v>,這樣就會跳過一些中間點。
代碼:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<set> #include<queue> #include<stack> #include<map> #include<vector> using namespace std; typedef long long ll; typedef pair<int,int> P; const int maxn=300,maxm=1e5+1000,inf=0x3f3f3f3f,mod=1e9+7; const ll INF=1e18+7; int n,m; vector<int>G[maxn]; bool used[maxn]; int cx[maxn],cy[maxn]; bool vis[maxn]; void pprintf(int u) { vis[u]=true; if(cx[u]<0) { printf("\n"); return ; } printf(" %d",cx[u]); pprintf(cx[u]); } bool dfs(int u) { for(int i=0; i<G[u].size(); i++) { int v=G[u][i]; if(used[v]) continue; used[v]=true; if(cy[v]<0||dfs(cy[v])) { cy[v]=u,cx[u]=v; return true; } } return false; } int solve() { int res=0; memset(cy,-1,sizeof(cy)); memset(cx,-1,sizeof(cx)); for(int i=1; i<=n; i++) { memset(used,false,sizeof(used)); res+=dfs(i); } memset(vis,false,sizeof(vis)); for(int i=1; i<=n; i++) { if(!vis[i]) { printf("%d",i); pprintf(i); } } printf("%d\n",n-res); } int main() { scanf("%d%d",&n,&m); int u,v; for(int i=1; i<=m; i++) { scanf("%d%d",&u,&v); G[u].push_back(v); } solve(); return 0; }最小路徑覆蓋
LiberOJ #6002. 「網絡流 24 題」最小路徑覆蓋