poj1469(最大二分匹配)
阿新 • • 發佈:2018-12-11
題目大意:
一共有N個學生跟P門課程,一個學生可以任意選一
門或多門課,問是否達成:
1.每個學生選的都是不同的課(即不能有兩個學生選同一門課)
2.每門課都有一個代表(即P門課都被成功選過)
輸入為:
P N(課程數跟學生數)
接著有P行,格式為Count studenti studenti+1 ……studentcount
(Count表示對課程1感興趣的學生數,接著有Count個學生)
如第一行3 1 2 3表示學生1跟學生2跟學生3對課程1感興趣
輸出為:
若能滿足上面兩個要求這輸出”YES”,否則為”NO”
思路:其實只是一道二分最大匹配的裸題,關鍵在於演算法的選擇上,一開始選了最大流法,超時。後來選了匈牙利演算法,不僅程式碼簡單,而且速度快。碰上二分最大匹配還是用匈牙利演算法吧,心累。
//用dinic演算法,當最大流來做,超時!!!!所以可以看看後面的匈牙利演算法
匈牙利演算法:
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<vector> #define inf 0x3f3f3f3f using namespace std; int n,p; int map[300][300],chk[300],used[300]; int find(int u) { for(int i=1;i<=n;i++) { if(map[u][i]&&!chk[i]) { chk[i]=1; if(!used[i]||find(used[i])) { used[i]=u; return 1; } } } return 0; } void solve() { int res=0; memset(used,0,sizeof(used)); for(int i=1;i<=p;i++) { memset(chk,0,sizeof(chk)); res+=find(i); } if(res==p) printf("YES\n"); else printf("NO\n"); } int main() { //freopen("t.txt","r",stdin); int w,t,a; scanf("%d",&w); while(w--) { memset(map,0,sizeof(map)); scanf("%d%d",&p,&n); for(int i=1;i<=p;i++) { scanf("%d",&t); while(t--) { scanf("%d",&a); map[i][a]=1; } } solve(); } return 0; }
dinic法:
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<vector> #define inf 0x3f3f3f3f using namespace std; int p,n; int dis[809],M; struct node { int v,cap,id; node(int v1,int cap1,int id1) { v=v1,cap=cap1,id=id1; } }; vector<node> map[405]; void add(int u,int v,int cap) { int l1=map[u].size(); int l2=map[v].size(); map[u].push_back(node(v,cap,l2)); map[v].push_back(node(u,0,l1)); } bool bfs() { queue<int> que; memset(dis,0,sizeof(dis)); dis[0]=1; que.push(0); while(!que.empty()) { int t=que.front();que.pop(); for(int i=0;i<map[t].size();i++) { if(!map[t][i].cap) continue; int v=map[t][i].v; if(!dis[v]) { dis[v]=dis[t]+1; if(v==M) return true; que.push(v); } } } return false; } int dfs(int u,int cap) { if(u==M) return cap; int tp=cap,t; for(int i=0;i<map[u].size();i++) { if(!map[u][i].cap) continue; int v=map[u][i].v; if(dis[v]==dis[u]+1) { t=dfs(v,min(tp,map[u][i].cap)); tp-=t; map[u][i].cap-=t; map[v][map[u][i].id].cap+=t; } } return cap-tp; } void dinic() { int ans=0; while(bfs()) { ans+=dfs(0,inf); } if(ans==p) printf("YES\n"); else printf("NO\n"); } int main() { //freopen("t.txt","r",stdin); int w,t,a; scanf("%d",&w); while(w--) { for(int i=0;i<405;i++) map[i].clear(); scanf("%d%d",&p,&n); M=p+n+1; for(int i=1;i<=p;i++) add(0,i,1); for(int i=1;i<=n;i++) add(p+i,p+n+1,1); for(int i=1;i<=p;i++) { scanf("%d",&t); while(t--) { scanf("%d",&a); add(i,a+p,1); } } dinic(); } return 0; }