zoukankan      html  css  js  c++  java
  • SPOJ 839 Optimal Marks(最小割的应用)

    https://vjudge.net/problem/SPOJ-OPTM

    题意:

    给出一个无向图G,每个点 v 以一个有界非负整数 lv 作为标号,每条边e=(u,v)的权w定义为该边的两个端点的标号的异或值,即W=lu XOR lv。现已知其中部分点的标号,求使得该图的总边权和最小的标号赋值。即最小化:

    思路:

    这道题目在刘伯涛的论文里讲得十分的详细,看看论文就可以啦。

    XOR运算是根据二进制的每一位来计算的,,并且因为每一位都是相互独立的,互不影响,所以可以转化为下式:

    接下来对于每一位都新建图,对于已经标号的顶点来说,如果该位是1,则与源点相连,否则与汇点相连,容量均为INF。如果本来就相连的点还是需要相连的,容量为1。对于每个还没有标号的点来说,在这一位的取值要么是1,要么是0,这就很符合最小割。在跑完最大流之后,只需要从源点出发,凡是能到达的点都是取值为1的。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef pair<int,int> pll;
     14 const int INF = 0x3f3f3f3f;
     15 const int maxn = 5000 + 5;
     16 
     17 int n, m, k;
     18 int val[maxn];
     19 int ans[maxn];
     20 int vis[maxn];
     21 int mp[maxn][maxn];
     22 
     23 struct Edge
     24 {
     25     int from,to,cap,flow;
     26     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
     27 };
     28 
     29 struct Dinic
     30 {
     31     int n,m,s,t;
     32     vector<Edge> edges;
     33     vector<int> G[maxn];
     34     bool vis[maxn];
     35     int cur[maxn];
     36     int d[maxn];
     37 
     38     void init(int n)
     39     {
     40         this->n=n;
     41         for(int i=0;i<n;++i) G[i].clear();
     42         edges.clear();
     43     }
     44 
     45     void AddEdge(int from,int to,int cap)
     46     {
     47         edges.push_back( Edge(from,to,cap,0) );
     48         edges.push_back( Edge(to,from,0,0) );
     49         m=edges.size();
     50         G[from].push_back(m-2);
     51         G[to].push_back(m-1);
     52     }
     53 
     54     bool BFS()
     55     {
     56         queue<int> Q;
     57         memset(vis,0,sizeof(vis));
     58         vis[s]=true;
     59         d[s]=0;
     60         Q.push(s);
     61         while(!Q.empty())
     62         {
     63             int x=Q.front(); Q.pop();
     64             for(int i=0;i<G[x].size();++i)
     65             {
     66                 Edge& e=edges[G[x][i]];
     67                 if(!vis[e.to] && e.cap>e.flow)
     68                 {
     69                     vis[e.to]=true;
     70                     d[e.to]=d[x]+1;
     71                     Q.push(e.to);
     72                 }
     73             }
     74         }
     75         return vis[t];
     76     }
     77 
     78     int DFS(int x,int a)
     79     {
     80         if(x==t || a==0) return a;
     81         int flow=0, f;
     82         for(int &i=cur[x];i<G[x].size();++i)
     83         {
     84             Edge &e=edges[G[x][i]];
     85             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
     86             {
     87                 e.flow +=f;
     88                 edges[G[x][i]^1].flow -=f;
     89                 flow +=f;
     90                 a -=f;
     91                 if(a==0) break;
     92             }
     93         }
     94         return flow;
     95     }
     96 
     97     int Maxflow(int s,int t)
     98     {
     99         this->s=s; this->t=t;
    100         int flow=0;
    101         while(BFS())
    102         {
    103             memset(cur,0,sizeof(cur));
    104             flow +=DFS(s,INF);
    105         }
    106         return flow;
    107     }
    108 }DC;
    109 
    110 void dfs(int u, int x)
    111 {
    112     vis[u]=1;
    113     ans[u]+=x;
    114     for(int i=0;i<DC.G[u].size();i++)
    115     {
    116         Edge& e=DC.edges[DC.G[u][i]];
    117         if(!vis[e.to] && e.cap>e.flow)
    118             dfs(e.to,x);
    119     }
    120 }
    121 
    122 void solve()
    123 {
    124     int src=0,dst=n+1;
    125     int bite=1;
    126     while(true)
    127     {
    128         DC.init(dst+1);
    129         for(int i=1;i<=n;i++)
    130             for(int j=1;j<=n;j++)
    131             if(mp[i][j]) DC.AddEdge(i,j,1);
    132 
    133         bool flag=false;
    134         for(int i=1;i<=n;i++) 
    135         {
    136             if(val[i]!=-1)
    137             {
    138                 if(val[i]>=1)
    139                 {
    140                     flag=true;
    141                 }
    142                 if(val[i]&1)
    143                 {
    144                     DC.AddEdge(src,i,INF);
    145                 }
    146                 else
    147                 {
    148                     DC.AddEdge(i,dst,INF);
    149                 }
    150                 val[i]>>=1;
    151             }
    152         }
    153 
    154         if(!flag)  break;
    155         DC.Maxflow(src,dst);
    156         memset(vis,0,sizeof(vis));
    157         dfs(src,bite);
    158         bite<<=1;
    159     }
    160 }
    161 
    162 int main()
    163 {
    164     //freopen("in.txt","r",stdin);
    165     int T;
    166     scanf("%d",&T);
    167     while(T--)
    168     {
    169         memset(mp,0,sizeof(mp));
    170         scanf("%d%d",&n,&m);
    171         for(int i=0;i<m;i++)
    172         {
    173             int u,v;
    174             scanf("%d%d",&u,&v);
    175             mp[u][v]=mp[v][u]=1;
    176         }
    177         memset(val,-1,sizeof(val));
    178         scanf("%d",&k);
    179         for(int i=0;i<k;i++)
    180         {
    181             int u,v;
    182             scanf("%d%d",&u,&v);
    183             val[u]=v;
    184         }
    185         memset(ans,0,sizeof(ans));
    186         solve();
    187         for(int i=1;i<=n;i++)
    188         {
    189             printf("%d
    ",ans[i]);
    190         }
    191     }
    192     return 0;
    193 }
  • 相关阅读:
    python使用消息队列RabbitMq(入门)
    python Condition类(锁)
    python锁
    python多线程的几种情形分析-三种情况
    git基本使用
    python学习笔记之数据类型、字符编码、文件处理
    NOIP2018提高组模拟题(五)
    10.28模拟赛
    差分+树状数组【p4868】Preprefix sum
    线段树【p2706】贪婪大陆
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7643114.html
Copyright © 2011-2022 走看看