task - 最小割

题目大意:
有一个k元组的可重集合S,|S|=n,定义两个k元组的加法是每一元分别相加得到都k元组。求S的一个子集,使得这些k元组加起来的字典序最大。
有m条限制形如如果想选x就必须选y。
n 1000 , m 5000 , k 5 n\le1000,m\le5000,k\le5
题解:
场上依次写了 n 20 , m = 0 n\le20,m=0 ,限制是链和一棵树的情况……
正解是直接去跑最大权闭合子图,重载一下int类型为这个k元组即可……
玄妙异常……并不能感性理解为啥是对的。

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;const int N=1010,M=40010,output_var=1000;
inline int inn() { int x,ch;while((ch=gc)<'0'||ch>'9');x=ch^'0';while((ch=gc)>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0');return x; }
struct node{
	static int k;int a[7];node(){memset(a,0,sizeof a);}node(const node &b){rep(i,1,k)a[i]=b.a[i];}
	inline node& operator=(const node &b) { rep(i,1,k) a[i]=b.a[i];return *this; }
	inline bool operator<(const node &b)const{rep(i,1,k) if(a[i]^b.a[i]) return a[i]<b.a[i];return false;}
	inline bool operator>(const node &b)const{rep(i,1,k) if(a[i]^b.a[i]) return a[i]>b.a[i];return false;}
	inline node operator+(const node &b)const{node c;rep(i,1,k) c.a[i]=a[i]+b.a[i];return c;}
	inline node operator-(const node &b)const{node c;rep(i,1,k) c.a[i]=a[i]-b.a[i];return c;}
	inline node& operator+=(const node &b){rep(i,1,k) a[i]+=b.a[i];return *this; }
	inline node& operator-=(const node &b){rep(i,1,k) a[i]-=b.a[i];return *this; }
	inline bool operator==(const node &b)const{rep(i,1,k) if(a[i]^b.a[i]) return false;return true; }
	inline int show()const{ rep(i,1,k) printf("%d ",a[i]+output_var);return !printf("\n"); }
}rw[N],INF,zero,ans;int node::k=0;
struct edges{int to,pre;node resf;}e[M];int h[N],etop,lev[N],cur[N];queue<int> q;
inline int add_edge(int u,int v,node f) { return e[++etop].to=v,e[etop].resf=f,e[etop].pre=h[u],h[u]=etop; }
inline int build_edge(int u,int v,node f) { return add_edge(u,v,f),add_edge(v,u,zero); }
inline bool bfs(int s,int t)
{
	while(!q.empty()) q.pop();memset(lev,0,sizeof(int)*(t+1)),q.push(s),lev[s]=1;
	for(int i,x,y;!q.empty();q.pop()) for(i=h[x=q.front()],y;i;i=e[i].pre)
		if(!lev[y=e[i].to]&&e[i].resf>zero) lev[y]=lev[x]+1,q.push(y);return lev[t]>0;
}
node dfs(int s,int t,node a)
{
	if(s==t||a==zero) return a;node f,flow;
	for(int &i=cur[s];i;i=e[i].pre)
		if(lev[e[i].to]==lev[s]+1&&(f=dfs(e[i].to,t,min(a,e[i].resf)))>zero)
		{	e[i].resf-=f,e[((i-1)^1)+1].resf+=f,a-=f,flow+=f;if(a==zero) break;	}
	return flow;
}
inline node dinic(int s,int t) { node flow;while(bfs(s,t)) memcpy(cur,h,sizeof(int)*(t+1)),flow+=dfs(s,t,INF);return flow; }
int main()
{
	int n=inn(),m=inn(),x,y;node::k=inn();char str[10];
	for(int i=1,j;i<=n;i++) for(scanf("%s",str+1),j=1;j<=node::k;j++)
		if(str[j]=='+') rw[i].a[j]=1;else if(str[j]=='-') rw[i].a[j]=-1;else rw[i].a[j]=0;
	rep(i,1,node::k) INF.a[i]=100000;int s=n+1,t=s+1;
	rep(i,1,n) if(rw[i]<zero) build_edge(i,t,zero-rw[i]);else build_edge(s,i,rw[i]),ans+=rw[i];
	while(m--) x=inn(),y=inn(),build_edge(x,y,INF);return (ans-dinic(s,t)).show(),0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82841380