CodeForces
Round #227 (Div .2) George and Interesting Graph
http://codeforces.com/contest/387/problem/D
模型:给n个点,m条有向边,可以删边,可以加边,问最少几次操作可以使每个点出度入度为一;
拆点,二分图,设最大匹配为leng,则答案为n - leng + m - leng; 提前是可以加自环;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<iostream> 5 #include<algorithm> 6 #include<cmath> 7 #include<cstdlib> 8 using namespace std; 9 const int N = 1000+10; 10 int u[N], v[N]; 11 int n, m; 12 vector<int> G[N]; 13 int vis[N], ny[N]; 14 int find(int u) { 15 for (int i = 0; i < (int)G[u].size(); i++) { 16 int v = G[u][i]; 17 if (vis[v]) continue; 18 vis[v] = 1; 19 if (ny[v] == -1 || find(ny[v])) { 20 ny[v] = u; 21 return 1; 22 } 23 } 24 return 0; 25 } 26 int Max_match() { 27 int ret = 0; 28 memset(ny, -1, sizeof(ny)); 29 for (int i = 1; i <= n; i++) { 30 memset(vis, 0, sizeof(vis)); 31 if (find(i)) ret++; 32 } 33 return ret; 34 } 35 int solve(int center) { 36 int cntWithI = 0; 37 for (int i = 0; i < m; i++) { 38 if (u[i] == center || v[i] == center) cntWithI++; 39 } 40 int other = m - cntWithI; 41 for (int i = 0; i <= n; i++) G[i].clear(); 42 for (int i = 0; i < m; i++) { 43 if (u[i] == center || v[i] == center) continue; 44 G[u[i]].push_back(v[i]); 45 } 46 int leng = Max_match(); 47 return 2*n-1 - cntWithI + other - leng + n-1 - leng; 48 } 49 int main() { 50 while (cin>>n>>m) { 51 for (int i = 0; i < m; i++) cin>>u[i]>>v[i]; 52 int ans = 1000000000; 53 for (int i = 1; i <= n; i++) { 54 ans = min(ans, solve(i)); 55 } 56 cout<<ans<<endl; 57 } 58 return 0; 59 }