1. 程式人生 > >洛谷 P2763 試題庫問題【最大流】

洛谷 P2763 試題庫問題【最大流】

mark etc pos -m nic %d namespace getch get

s向所有類別屬性連流量為當前類別屬性需要的個數的邊,所有題目向t連流量為1的邊(表示只能選一次),所有屬性向含有它的題連容量為1的邊。跑一變dinic,結果小於m則無解,否則看每一個類別屬性連出去的題目的邊是否滿流,滿流代表這個屬性選擇這道題

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=1000005,inf=1e9;
int n,m,h[N],cnt=1,s,t,le[N],sum;
bool vs[N],vt[N];
string c;
struct
qwe { int ne,to,va; }e[N<<1]; int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } void
add(int u,int v,int w) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; e[cnt].va=w; h[u]=cnt; } void ins(int u,int v,int w) {//cout<<u<<" "<<v<<" "<<w<<endl; add(u,v,w); add(v,u,0); } bool bfs() { queue<int>q; memset(le,0,sizeof(le)); le[s]=1
; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=h[u];i;i=e[i].ne) if(e[i].va>0&&!le[e[i].to]) { le[e[i].to]=le[u]+1; q.push(e[i].to); } } return le[t]; } int dfs(int u,int f) { if(u==t||f==0) return f; int us=0; for(int i=h[u];i&&us<f;i=e[i].ne) if(e[i].va>0&&le[e[i].to]==le[u]+1) { int t=dfs(e[i].to,min(e[i].va,f-us)); e[i].va-=t; e[i^1].va+=t; us+=t; } if(!us) le[u]=0; return us; } int dinic() { int re=0; while(bfs()) re+=dfs(s,inf); return re; } int main() { m=read(),n=read(); s=0,t=m+n+1; for(int i=1;i<=m;i++) { int x=read(); sum+=x; ins(s,i,x); } for(int i=1;i<=n;i++) { int p=read(); for(int j=1;j<=p;j++) { int x=read(); ins(x,i+m,1); } ins(i+m,t,1); } if(dinic()<sum) { puts("No Solution!"); return 0; } for(int u=1;u<=m;u++) { printf("%d: ",u); for(int i=h[u];i;i=e[i].ne) if(e[i].to!=s&&!e[i].va) printf("%d ",e[i].to-m); puts(""); } return 0; }

洛谷 P2763 試題庫問題【最大流】