标签:blog class code int string 2014
HDU 2063
求一个二分图的最大匹配。
完全的裸题。贴代码。
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<iostream> using namespace std; vector<int> G[1005]; bool check[1005]; int mac[1005]; int n; void add_edge(int from,int to) { G[from].push_back(to); G[to].push_back(from); } bool dfs(int u) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!check[v]) { check[v]=1; if(mac[v]==-1||dfs(mac[v])) { mac[u]=v; mac[v]=u; return 1; } } } return 0; } int xyl() { int ans=0; memset(mac,-1,sizeof(mac)); for(int i=1;i<=n;i++) { if(mac[i]==-1) { memset(check,0,sizeof(check)); if(dfs(i)) { ans++; } } } return ans; } int main() { int k,n1,m1; while(scanf("%d",&k)!=EOF) { if(k==0) return 0; scanf("%d%d",&n1,&m1); n=n1+m1; for(int i=1;i<=n;i++) G[i].clear(); while(k--) { int A,B; scanf("%d%d",&A,&B); add_edge(A,B+n1); } printf("%d\n",xyl()); } }
判断该图是否为二分图,如果是二分图就求该图的最大匹配。
判断是否为二分图是我用了一个DFS 也不知道还有没有更简单的方法。
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<stack> #include<math.h> #include<iostream> using namespace std; vector<int> G[205]; bool check[205]; int mac[205]; int re[205]; void add_edge(int from,int to) { G[from].push_back(to); G[to].push_back(from); } bool rdfs(int u,int k) { re[u]=k; bool flag=true; int k1; if(k==1) k1=2; else k1=1; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(re[v]==k) { flag=false; break; } else if(re[v]==0) { flag=rdfs(v,k1); if(!flag) break; } } return flag; } bool dfs(int u) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!check[v]) { check[v]=true; if(mac[v]==-1||dfs(mac[v])) { mac[u]=v; mac[v]=u; return true; } } } return false; } int n; int xyl() { int ans=0; memset(mac,-1,sizeof(mac)); for(int i=1;i<=n;i++) { if(mac[i]==-1) { memset(check,0,sizeof(check)); check[i]=1; if(dfs(i)) ans++; } } return ans; } int main() { int m; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) G[i].clear(); while(m--) { int A,B; scanf("%d%d",&A,&B); add_edge(A,B); } memset(re,0,sizeof(re)); bool flag=0; for(int i=1;i<=n;i++) { if(re[i]==0) { if(!rdfs(i,1)) { flag=1; break; } } } if(flag==1) printf("No\n"); else { printf("%d\n",xyl()); } } }
题意:一个棋盘上有一些地方能放“车” 求最多能放多少个,又有多少个点是关键点,关键点——删除这个点能放的“车”会变少。
把行归位X集合 列归为Y集合。每个点就是从X-Y的一条边。
进行二分图匹配。然后枚举边,求出删除这条边之后的最大匹配,如果比之前的少了 就是关键点。
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<iostream> using namespace std; int mac[205]; bool check[205]; vector<int> G[205]; int z,y; int n; int k[10005][2]; void add_edge(int from,int to) { G[from].push_back(to); G[to].push_back(from); } bool dfs(int u) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if((u==z&&v==y)||(u==y&&v==z)) continue; if(!check[v]) { check[v]=1; if(mac[v]==-1||dfs(mac[v])) { mac[u]=v; mac[v]=u; return true; } } } return false; } int xyl() { memset(mac,-1,sizeof(mac)); int ans=0; for(int i=1;i<=n;i++) { if(mac[i]==-1) { memset(check,0,sizeof(check)); if(dfs(i)) ans++; } } return ans; } int main() { int N,M,K; int Case=0; while(scanf("%d%d%d",&N,&M,&K)!=EOF) { for(int i=1;i<=N+M;i++) G[i].clear(); int r=0; n=N+M; while(K--) { int A,B; scanf("%d%d",&A,&B); k[r][0]=A; k[r][1]=B+N; r++; add_edge(A,B+N); } z=0;y=0; int ans=xyl(); //printf("%d\n",ans); int sum=0; for(int i=0;i<r;i++) { z=k[i][0]; y=k[i][1]; int ans1=xyl(); if(ans1!=ans) { sum++; } } printf("Board %d have %d important blanks for %d chessmen.\n",++Case,sum,ans); } }
标签:blog class code int string 2014
原文地址:http://blog.csdn.net/u012896700/article/details/24850051