SPOJ OPTM(最小割)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qkoqhh/article/details/82710518

这个首先是可以安位考虑的,按位拆完之后变成01,那么有贡献的边必定是01边,这个符合割边的定义,那么就转化成求最小割了。。

由于确定的点不能改变,所以他们按照01分别向S和T连容量为无穷大的边,原图的无向边拆成2个有向边,容量为1,这样就能求最小值了。。

然后对方案的要求是点权和最小,那么就是在同取1和0的情况下要取0。。这个。。直接把原图的流量扩容,然后往1代表的点集连一个容量为1的边,这样就能在保证正确性的情况下尽可能取0。。。

/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          ┃   ┃   神兽保佑,代码无bug
 *          ┃   ┃           
 *          ┃   ┃        
 *          ┃   ┃
 *          ┃   ┃           
 *          ┃   ┗━━━┓
 *          ┃       ┣┓
 *          ┃       ┏┛
 *          ┗┓┓┏━┳┓┏┛
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛
 */ 
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-12
#define succ(x) (1<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 505
#define nm 40005
#define pi 3.1415926535897931
const int inf=1e9;
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
 
 
 
 
 
struct edge{int t,v;edge*next,*rev;}e[nm],*h[NM],*o=e,*p[NM],*tmp[NM];
void _add(int x,int y,int v){o->t=y;o->v=v;o->next=h[x];h[x]=o++;}
void add(int x,int y,int v){_add(x,y,v);_add(y,x,0);h[x]->rev=h[y];h[y]->rev=h[x];}
int n,m,tot,a[NM],ans[NM],_x,_y;
int d[NM],cnt[NM];
struct tmp{int x,y;}b[nm];




void maxflow(){
    edge*j;
    mem(d);mem(cnt);mem(tmp);mem(p);
    tot=n+1;cnt[0]=tot;
    inc(i,0,n)tmp[i]=h[i];
    for(int x=0,s=inf;d[x]<tot;){
	for(j=tmp[x];j;j=j->next)if(j->v&&d[x]==d[j->t]+1)break;
	if(j){
	    s=min(s,j->v);tmp[x]=p[j->t]=j;
	    if((x=j->t)==n){
		for(;p[x];x=p[x]->rev->t)p[x]->v-=s,p[x]->rev->v+=s;
		s=inf;
	    }
	}else{
	    if(!--cnt[d[x]])break;d[x]=tot;
	    link(x)if(j->v&&d[x]>d[j->t]+1)tmp[x]=j,d[x]=d[j->t]+1;
	    cnt[d[x]]++;
	    if(p[x])x=p[x]->rev->t;
	}
    }
}

bool v[NM];
queue<int>q;

void bfs(){
    mem(v);q.push(0);v[0]++;
    while(!q.empty()){
	int t=q.front();q.pop();
	link(t)if(j->v&&!v[j->t])q.push(j->t),v[j->t]++;
    }
}


int main(){
    int _=read();while(_--){
	mem(ans);mem(a);
	n=read();m=read();
	inc(i,1,m)b[i].x=read(),b[i].y=read();
	inc(i,1,n)a[i]=-1;
	tot=read();
	while(tot--){_x=read();a[_x]=read();}
	inc(p,1,31){
	    mem(e);mem(h);o=e;
	    inc(i,1,n)if(a[i]==-1)add(0,i,1);
	    else if(a[i]&succ(p-1))add(i,n+1,inf);else add(0,i,inf);
	    inc(i,1,m)add(b[i].x,b[i].y,1000),add(b[i].y,b[i].x,1000);
	    n++;
	    maxflow();
	    bfs();
	    n--;
	    inc(i,1,n)if(!v[i])ans[i]|=succ(p-1);
	}
	inc(i,1,n)printf("%d\n",ans[i]);
    }
    return 0;
}

Optimal Marks

SPOJ - OPTM

You are given an undirected graph G(V, E). Each vertex has a mark which is an integer from the range [0..231 – 1]. Different vertexes may have the same mark.

For an edge (u, v), we define Cost(u, v) = mark[u] xor mark[v].

Now we know the marks of some certain nodes. You have to determine the marks of other nodes so that the total cost of edges is as small as possible.

Input

The first line of the input data contains integer T (1 ≤ T ≤ 10) - the number of testcases. Then the descriptions of T testcases follow.

First line of each testcase contains 2 integers N and M (0 < N <= 500, 0 <= M <= 3000). N is the number of vertexes and M is the number of edges. Then M lines describing edges follow, each of them contains two integers u, v representing an edge connecting u and v.

Then an integer K, representing the number of nodes whose mark is known. The next K lines contain 2 integers u and p each, meaning that node u has a mark p. It’s guaranteed that nodes won’t duplicate in this part.

Output

For each testcase you should print N lines integer the output. The Kth line contains an integer number representing the mark of node K. If there are several solutions, you have to output the one which minimize the sum of marks. If there are several solutions, just output any of them.

Example

Input:
1
3 2
1 2
2 3
2
1 5
3 100

Output:
5
4
100 

猜你喜欢

转载自blog.csdn.net/qkoqhh/article/details/82710518