zoukankan      html  css  js  c++  java
  • 【SPOJ839】最优标号

    【题目描述】

    给你一张无向图G(V,E)。每个顶点都有一个标号,它是一个[0,2^31-1]内的整数。不同的顶点可能会有相同的标号。

    对每条边(u,v),我们定义其费用cost(u,v)为u的标号与v的标号的异或值。

    现在我们知道一些顶点的标号。你需要确定余下顶点的标号使得所有边的费用和尽可能小。

    【输入格式】

    输入文件的第一行有两个整数N,M(1<=N<=500,0<=M<=3000),N是图的点数,M是图的边数。

    接下来有M行,每行有两个整数u,v,代表一条连接u,v的边。

    接下来有一个整数K,代表已知标号的顶点个数。接下来的K行每行有两个整数u,p,代表点u的标号是p。假定这些u不会重复。

    【输出格式】

    输出一行一个整数,即最小的费用和。

    【分析】

    由题目叙述中,我们可以很容易看到,对于每个顶点的标号数的每个二进制位上来说,它与前后该数的其他二进制位是完全没有任何联系的,所以我们不妨把每个数的二进制位拆开来组图,然后再求每个图的最小割就可以了。

    在建图的时候,要注意的是,需要把二进制位上为1的和二进制位上为0的分开连接到源点和汇点。

    最后,注意重边!

      1 #include <cstdlib>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <cstdio>
      6 #include <queue>
      7 const int maxn=510;
      8 const int maxm=3010;
      9 const int INF=10000*10000;
     10 using namespace std;
     11 struct liu
     12 {
     13        int c,f;
     14        liu(){c=0;f=0;}
     15 }maps[maxn][maxn];
     16 int shu[maxn],map[maxn][maxn];
     17 int bh[maxn],path[maxn],dist[maxn];
     18 
     19 int n,m,k;
     20 long long solve(int times);
     21 void make_maps(int times);
     22 bool BFS();
     23 int dfs(int u,int low);
     24 
     25 int main()
     26 {
     27     int i;
     28     memset(shu,-1,sizeof(shu));
     29     memset(map,0,sizeof(map));
     30     //读入数据 
     31     scanf("%d%d",&n,&m);
     32     for (i=1;i<=m;i++) 
     33     {
     34         int u,v;
     35         scanf("%d%d",&u,&v);
     36         map[u][v]++;
     37         map[v][u]++;
     38     }
     39     scanf("%d",&k);
     40     for (i=1;i<=k;i++) 
     41     {
     42         int u,p;
     43         scanf("%d%d",&u,&p);
     44         shu[u]=p;
     45     }
     46     
     47     long long ans=0;
     48     //注意求解次数 
     49     for (i=0;i<=31;i++) ans+=solve(i);//求解最大流 
     50     printf("%lld",ans);
     51     return 0;
     52 }
     53 //求解函数 
     54 long long solve(int times)
     55 {
     56      int i,flow=0,pos;
     57      
     58      make_maps(times);
     59      while ( BFS() )
     60      {
     61            int now;
     62            while (now=dfs(0,INF)) flow+=now;
     63            //printf("%d
    ",now);
     64      }
     65      //printf("%d
    ",flow);
     66      return (long long)flow<<times;
     67 }
     68 //构图 
     69 void make_maps(int times)
     70 {
     71      int i,j,bh[maxn];
     72      //-1代表还没有开始标号 
     73      memset(bh,-1,sizeof(bh));
     74      memset(maps,0,sizeof(maps));
     75      for (i=1;i<=n;i++) 
     76      {
     77          if (shu[i]==-1) continue;
     78          bh[i]=((1<<times)&shu[i])==(1<<times);//二进制位
     79          //超级源汇
     80          if (bh[i]!=0) {maps[0][i].f=0;maps[0][i].c=INF;}
     81          else {maps[i][n+1].f=0;maps[i][n+1].c=INF;}
     82      }
     83      for (i=1;i<=n;i++)
     84      for (j=1;j<=n;j++)
     85      {
     86          if (map[i][j]==0) continue;//保留原边 
     87          maps[i][j].c=map[i][j];
     88          maps[i][j].f=0;
     89      }
     90      return;
     91 }
     92 bool BFS()//BFS构建层次网络 
     93 {
     94      int i,u;
     95      queue<int>Q;
     96      memset(dist,-1,sizeof(dist));
     97      dist[0]=0;
     98      Q.push(0);
     99      while (!Q.empty())
    100      {
    101            int u=Q.front();Q.pop();
    102            for (i=0;i<=n+1;i++)
    103            {
    104                int v=i;
    105                if (dist[v]==-1 && maps[u][v].c-maps[u][v].f>0)
    106                {
    107                    Q.push(v);
    108                    dist[v]=dist[u]+1;
    109                }
    110            }
    111      } 
    112      return (dist[n+1]!=-1);
    113 }
    114 int dfs(int v,int low)//增广 
    115 {
    116     int i;
    117     if (v==(n+1) || low==0) return low;
    118     int flow=0,f;
    119     for (i=0;i<=(n+1);i++)
    120     {
    121         if (maps[v][i].c-maps[v][i].f>0 && dist[i]==dist[v]+1)
    122         {
    123             if (f=dfs(i,min(low,maps[v][i].c-maps[v][i].f)))
    124             {
    125                 maps[v][i].f+=f;
    126                 maps[i][v].f-=f;
    127                 flow+=f;
    128                 low-=f;
    129                 if (low==0) break;
    130             }
    131         } 
    132     }
    133     return flow;
    134 }
    View Code
  • 相关阅读:
    sentinel使用内置规则检测威胁——自定义规则是使用的KQL
    在Azure Sentinel中使用威胁情报——可以自己订阅,自己创建一条indicator来使用基于情报的检测
    sm2国密算法的纯c语言版本,使用于单片机平台(静态内存分配)
    JDK-8180048 : Interned string and symbol table leak memory during parallel unlinking
    CMS垃圾收集器小实验之CMSInitiatingOccupancyFraction参数
    记spring boot线上项目内存优化
    springboot 配置log4j2日志,并输出到文件
    SpringBoot 日志管理之自定义Appender
    Linux 上 定时备份postgresql 数据库的方法
    linux下执行sh脚本,提示Command not found解决办法
  • 原文地址:https://www.cnblogs.com/hoskey/p/3721837.html
Copyright © 2011-2022 走看看