• SPOJ 839 最小割


    题意:

    给出一些权已知的点(剩下的点的权未知),以及所有点之间的边的关系,每条边的权是其两端点的点权值的异或值,求未知点的权是什么的时候所有边权的和最小

    题解:

    amber的论文题,简直太绝了!

    http://kanboxshare.com/link/v0yHI2oUoSNMCo8mAmj1Bxy0mqMIH6tZNUsbGxG4mvu3FNl9FfiODWiEmdvTHKBRNUbpNxELmvNwA2rCFwu1DeAXb0I7HoBFNmIvNVIXmNYmFNl43dPYfIaGnVeFDB5XszPnT5jttcdCQ

    思想就是按位做32遍最小割。

    View Code
      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 
      7 #define N 1000
      8 #define M 400000
      9 #define INF 1e8
     10 
     11 using namespace std;
     12 
     13 int head[N],to[M],next[M],len[M];
     14 int q[M],layer[N],mark[N],pu[M],pv[M],ans[N];
     15 bool vis[N];
     16 int n,m,S,T,cnt,cas;
     17 
     18 inline void add(int u,int v,int w)
     19 {
     20     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
     21     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
     22 }
     23 
     24 inline void read()
     25 {
     26     scanf("%d%d",&n,&m);
     27     S=0; T=n+1;
     28     for(int i=1;i<=m;i++) scanf("%d%d",&pu[i],&pv[i]);
     29     memset(mark,-1,sizeof mark);
     30     memset(ans,0,sizeof ans);
     31     int tmp;
     32     scanf("%d",&tmp);
     33     for(int i=1,u,v;i<=tmp;i++)
     34     {
     35         scanf("%d%d",&u,&v);
     36         mark[u]=v;
     37     }
     38 }
     39 
     40 inline void build(int w)
     41 {
     42     memset(head,-1,sizeof head); cnt=0;
     43     for(int i=1;i<=n;i++)
     44         if(mark[i]!=-1)
     45         {
     46             if(mark[i]&(1<<w)) add(S,i,INF);
     47             else add(i,T,INF);
     48         }
     49     for(int i=1;i<=m;i++)
     50     {
     51         add(pu[i],pv[i],1);
     52         add(pv[i],pu[i],1);
     53     }
     54 }
     55 
     56 inline bool bfs()
     57 {
     58     memset(layer,-1,sizeof layer);
     59     int h=1,t=2,sta;
     60     q[1]=S; layer[S]=0;
     61     while(h<t)
     62     {
     63         sta=q[h++];
     64         for(int i=head[sta];~i;i=next[i])
     65             if(len[i]&&layer[to[i]]<0)
     66             {
     67                 layer[to[i]]=layer[sta]+1;
     68                 q[t++]=to[i];
     69             }
     70     }
     71     return layer[T]!=-1;
     72 }
     73 
     74 inline int find(int u,int cur_flow)
     75 {
     76     if(u==T) return cur_flow;
     77     int res=0,tmp;
     78     for(int i=head[u];~i&&res<cur_flow;i=next[i])
     79         if(len[i]&&layer[to[i]]==layer[u]+1)
     80         {
     81             tmp=find(to[i],min(cur_flow-res,len[i]));
     82             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
     83         }
     84     if(!res) layer[u]=-1;
     85     return res;
     86 }
     87 
     88 inline void dinic()
     89 {
     90     int ans=0;
     91     while(bfs()) ans+=find(S,INF);
     92 }
     93 
     94 inline void dfs(int u,int w)
     95 {
     96     if(u>=1&&u<=n) ans[u]|=(1<<w);
     97     vis[u]=true;
     98     for(int i=head[u];~i;i=next[i])
     99         if(len[i]>0&&!vis[to[i]]) dfs(to[i],w);
    100 }
    101 
    102 inline void go()
    103 {
    104     for(int i=0;i<32;i++)
    105     {
    106         build(i);
    107         dinic();
    108         memset(vis,0,sizeof vis);
    109         dfs(S,i);
    110     }
    111     for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
    112 }
    113 
    114 int main()
    115 {
    116     scanf("%d",&cas);
    117     while(cas--) read(),go();
    118     return 0;
    119 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    唯有坚持方能成功
    Java程序猿,你为什么要关注Scala
    HDU 2871 Memory Control(线段树)
    SQL 合并两个结果集 一个倒序,一个正序
    Charm Bracelet(poj3624)(01背包)
    Dijkstra算法,求单源最短路径(包括路径)
    aix平台安装10.2.0.5的CRS时遇到的bug
    Java语言基础系列之1--用IDEA编写HelloWorld
    UVA 10986 Sending email SPFA
    NumberProgressBar开源项目学习
  • 原文地址:https://www.cnblogs.com/proverbs/p/2852009.html
Copyright © 2020-2023  润新知