A network flow exercises

The meaning of problems

Existing game, you as a player, with k kinds of goods. Initially, each item has 1000.

Now, before you have n tasks, each task may consume some items, you may also get some items. Do i-th gains and losses where the task item with a string of letters containing Si k, where each letter is +, - A / the j-th letter indicates the number of the task item j influences. + Means to do this task can get an item j, - indicate to do this task will consume an item j, / expressed do this task does not have an impact on the number of items of j.

But do the task is a prerequisite condition. Game designers agreed limit of m relationship, every relationship is a limit on the number ordered (i, j), he expressed the need to do first before doing the task j task i.

Now, you need to do some selective task, make the most of the items were.

The method of comparing the number of items were the following two schemes: Comparative they get to the number of article 1, if the same, compare the article 2, if the same, compare the article 3, and so on.

data range

n 1000 , m 5000 , k 5 , Insurance certificate limit system turn off system in No Have ring n \ le 1000, m \ le 5000, k \ le 5, there is no guarantee restricted relation ring

solution

Consider a task reward like k digits, so to convert it into a decimal number, and then there are both positive and negative weights, consider limiting relations for construction diagram, the way to do that is if you do the task before the task j i, then j connected to one side, then ask for this figure from the maximum weight i closed subgraph. selected sub-graph is the answer.

Since I started to have doubts about the correctness of doing this, so now a little to prove it:

First, the maximum weight subgraph is closed by subtracting the original sum of all positive weights minimal cut, then we reverse the construction side relative to the limit, is to ask if you want to pick one point, all the points it must be before the election. this will meet the limit.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=1e18;
const int maxn=5e3+5;
inline int read(){
	char c=getchar();int t=0,f=1;
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
	return t*f;
}
int n,m,k;
ll p[maxn];
char c[maxn][5];
ll val[maxn];
inline int calc(char c){
	if(c=='+')return 1;
	if(c=='-')return -1;
	return 0;
}
struct edge{
	int v,p;
	ll w;
}e[maxn<<1];
int h[maxn],cnt=1;
inline void add(int a,int b,ll c){
	e[++cnt].p=h[a];
	e[cnt].v=b;
	e[cnt].w=c;
	h[a]=cnt;
}
int s,t,ht[maxn];
ll dis[maxn];
bool bfs(){
	queue<int> q;
	while(!q.empty())q.pop();
	q.push(s);
	memset(dis,0,sizeof(dis));
	dis[s]=1;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=h[u];i;i=e[i].p){
			int v=e[i].v;
			if(e[i].w&&dis[v]==0){
				dis[v]=dis[u]+1;q.push(v);
			}
		}
	}
	return dis[t];
}
ll dfs(int u,ll rest){
	if(rest==0||u==t){return rest;}
	ll tot=0;
	for(int &i=ht[u];i;i=e[i].p){
		int v=e[i].v;
		if(e[i].w&&dis[v]==dis[u]+1){
			ll di=dfs(v,min(rest,e[i].w));
			e[i].w-=di;e[i^1].w+=di;
			rest-=di;tot+=di;
			if(rest==0)break;
		}
	}
	return tot;
}
ll dinic(){
	ll ans=0;
	while(bfs()){
		ll di=0;
		for(int i=1;i<=t;i++)ht[i]=h[i];
		while(di=dfs(s,inf))ans+=di;
	}
	return ans;
}
ll tmp1[5],tmp2[5];
int main(){
	//freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
	n=read(),m=read(),k=read();s=n+1,t=n+2;
	p[0]=1;
	for(int i=1;i<k;i++)p[i]=p[i-1]*2*n;
	for(int i=1;i<=n;i++){
		scanf("%s",c[i]);
		for(int j=0;j<k;j++){
			val[i]+=p[k-1-j]*calc(c[i][j]);
		}
	}
	for(int i=1;i<=m;i++){
		int a=read(),b=read();
		add(a,b,inf);
		add(b,a,0);
	}
	ll sum=0;
	for(int i=1;i<=n;i++){
		if(val[i]>0){
			sum+=val[i];
			add(s,i,val[i]);add(i,s,0);
		}
		else{
			add(i,t,-val[i]);add(t,i,0);
		}
	}
	ll ans=dinic();
	if(sum<ans){
		for(int i=0;i<k;i++)printf("1000 ");
		return 0;
	}
	else{
		sum-=ans;
		for(int i=0;i<k;i++){
			if(p[1]){
				tmp1[k-1-i]+=sum%p[1];
				sum/=p[1];
			}
			else{
				tmp1[k-1-i]+=sum;
			}
			//printf("%d\n",tmp1[k-1-i]);
			if(tmp1[k-1-i]>n){
				tmp1[k-i-2]++;tmp1[k-1-i]=tmp1[k-1-i]-2*n;
				//printf("%d\n",k-i);
			}
		}
		for(int i=0;i<k;i++){
			printf("%lld ",1000+tmp1[i]);
		}
		return 0;
	}
	return 0;
}
Published 62 original articles · won praise 1 · views 979

Guess you like

Origin blog.csdn.net/wmhtxdy/article/details/103896631