• 【SPOJ839】Optimal Marks 网络流


    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 

    题目大意:
    每一条边的权值定义为x xor y,(x,y是两端点),有一些点的权值已知,求剩下的点怎么弄,是总边权最小。
    题解:
    首先要知道xor操作时,二进制的每一位都是独立的,不相互影响,所以可以分开处理。
    对于每一位,我们把未知的点初始为0,然后对已知的进行操作:当前位为1的S到i有一条边,容量为INF,为0则到T有一条为INF边。
    然后对于每一条边:(i,j)拆成(i,j,1)(j,i,1)
    然后跑最小割,可以发现对于每一个子图,最小割不是割在T就是割在S,割在T表示前面一堆点都设为1(
    因为已知的1比0多),隔在S表示后面一堆点都设为0(因为已知的0比1多)
    知道了这个,于是在跑完最小割之后就从S开始把能到的点都标为1。
    至于反向弧为什么为1,一是原图无向,二就是为了这个时候能全都遍历到。
    贴代码:
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int N=605,M=3005,INF=1999999999;
      7 int gi(){
      8     int str=0;char ch=getchar();
      9     while(ch>'9'||ch<'0')ch=getchar();
     10     while(ch>='0'&&ch<='9')str=str*10+ch-'0',ch=getchar();
     11     return str;
     12 }
     13 int n,m,mark[N];
     14 struct Edge{
     15     int x,y;
     16 }e[M];
     17 bool d[N];bool vis[N];
     18 int num=1,head[N],S=0,T;
     19 struct Lin{
     20     int next,to,dis;
     21 }a[M*10];
     22 void init(int x,int y,int z){
     23     a[++num].next=head[x];
     24     a[num].to=y;
     25     a[num].dis=z;
     26     head[x]=num;
     27     a[++num].next=head[y];
     28     a[num].to=x;
     29     a[num].dis=(z==INF?INF:1);
     30     head[y]=num;
     31 }
     32 int q[N],dep[N];
     33 bool bfs()
     34 {
     35     memset(dep,0,sizeof(dep));
     36     dep[S]=1;q[1]=S;int u,x,sum=1,t=0;
     37     while(t!=sum)
     38     {
     39         x=q[++t];
     40         for(int i=head[x];i;i=a[i].next){
     41             u=a[i].to;
     42             if(dep[u]||a[i].dis<=0)continue;
     43             dep[u]=dep[x]+1;q[++sum]=u;
     44         }
     45     }
     46     return dep[T];
     47 }
     48 int dfs(int x,int flow)
     49 {
     50     if(x==T || !flow)return flow;
     51     int tmp,sum=0,u;
     52     for(int i=head[x];i;i=a[i].next){
     53         u=a[i].to;
     54         if(dep[u]!=dep[x]+1 || a[i].dis<=0)continue;
     55         tmp=dfs(u,min(flow,a[i].dis));
     56         sum+=tmp;flow-=tmp;
     57         a[i].dis-=tmp;a[i^1].dis+=tmp;
     58         if(!flow)break;
     59     }
     60     return sum;
     61 }
     62 void maxflow(){
     63     int tmp;
     64     while(bfs()){
     65         tmp=dfs(S,INF);
     66         while(tmp)tmp=dfs(S,INF);
     67     }
     68 }
     69 void Reset(){
     70     memset(head,0,sizeof(head));
     71     memset(vis,0,sizeof(vis));
     72     num=1;
     73 }
     74 void remark(int x,int pa){
     75     vis[x]=true;
     76     if(!d[x])mark[x]+=pa;
     77     for(int i=head[x];i;i=a[i].next){
     78         if(a[i].dis>0 && !vis[a[i].to])remark(a[i].to,pa);
     79     }
     80 }
     81 void check(int fx)
     82 {
     83     Reset();
     84     int pa=(1<<fx);
     85     for(int i=1;i<=n;i++){
     86         if(!d[i])continue;
     87         if(mark[i]&pa)init(S,i,INF);
     88         else init(i,T,INF);
     89     }
     90     for(int i=1;i<=m;i++)init(e[i].x,e[i].y,1);
     91     maxflow();
     92     remark(S,pa);
     93 }
     94 void work()
     95 {
     96     int pp,x;
     97     n=gi();m=gi();
     98     T=n+1;
     99     for(int i=1;i<=m;i++)e[i].x=gi(),e[i].y=gi();
    100     pp=gi();
    101     for(int i=1;i<=pp;i++)x=gi(),mark[x]=gi(),d[x]=true;
    102     for(int i=0;i<=30;i++)check(i);
    103     for(int i=1;i<=n;i++)printf("%d
    ",mark[i]);
    104 }
    105 void Clear(){
    106     memset(mark,0,sizeof(mark));
    107     memset(d,0,sizeof(d));
    108 }
    109 int main()
    110 {
    111     //freopen("pp.in","r",stdin);
    112     int TT=gi();
    113     while(TT--){
    114         work();
    115         Clear();
    116     }
    117     return 0;
    118 }
    
    
    
     



  • 相关阅读:
    PLSQL Developer oracle导入导出表及数据
    Java之设计模式
    mySQL:两表更新(用一个表更新另一个表)的SQL语句
    Java中对图片文件的类型的获取
    JAVA判断文件的内容类型
    正确理解Mysql的列索引和多列索引
    eclipse快捷键
    C# 利用Jmail接收邮件
    github常见操作和常见错误!错误提示:fatal: remote origin already exists.
    css3特殊图形(气泡)
  • 原文地址:https://www.cnblogs.com/Yuzao/p/6867023.html
Copyright © 2020-2023  润新知