poj 2987
二分图最小点权覆盖。
代码:
#include<iostream> #include<fstream> #include<queue> #include<cmath> using namespace std; int n; int d[110]; double flow; int v[110]; typedef struct e{ int data; double f,c; e *next,*opt; }e; e edge[110]; int build(){ int i,j,k; queue<int> q; q.push(1); memset(d,0,sizeof(d)); d[1]=1; while(!q.empty()) { i=q.front(); q.pop(); e *p=edge[i].next; while(p) { j=p->data; if(d[j]==0&&p->c>p->f) { d[j]=d[i]+1; if(j==n) return 1; q.push(j); } p=p->next; } } return 0; } double find(int m,double minw){ int i,k; double j; if(m==n) return minw; v[m]=1; e *p=edge[m].next; while(p) { i=p->data; if(p->c>p->f&&d[i]==d[m]+1&&v[i]==0) { j=find(i,min(minw,p->c-p->f)); if(j) { p->f+=j; p->opt->f=p->f*(-1); return j; } } p=p->next; } return 0; } double solve(){ int j; double k; flow=0; double i; while(build()) while(1){ memset(v,0,sizeof(v)); i=10000000; k=find(1,i); flow+=k; if(k==0) break; } return flow; } void read(){ // ifstream cin("in.txt"); int i,j,k,s,t,m; double value; int K; cin>>K; while(K--) { memset(edge,0,sizeof(edge)); cin>>n>>m>>k; for(i=1;i<=n;i++) { cin>>value; e *p=new e; p->data=i+1; p->next=edge[1].next; edge[1].next=p; p->c=log(value); p->f=0; e *q=new e; q->data=1; q->next=edge[i+1].next; edge[i+1].next=q; q->c=q->f=0; p->opt=q; q->opt=p; } for(i=1;i<=m;i++) { cin>>value; e *p=new e; p->data=i+n+1; p->next=edge[n+m+2].next; edge[n+m+2].next=p; p->c=0; p->f=0; e *q=new e; q->data=n+m+2; q->next=edge[i+1+n].next; edge[i+1+n].next=q; q->f=0;q->c=log(value); p->opt=q; q->opt=p; } for(i=1;i<=k;i++) { cin>>s>>t; e *p=new e; p->data=t+1+n; p->next=edge[1+s].next; edge[1+s].next=p; p->c=10000000; p->f=0; e *q=new e; q->data=1+s; q->next=edge[t+n+1].next; edge[t+n+1].next=q; q->c=q->f=0; p->opt=q; q->opt=p; } n+=2+m; solve(); printf("%.4lf\n",exp(flow)); } } int main(){ read(); return 0; }