• Plug It In!(网络流板子)


    问题 E: Plug It In!

    时间限制: 12 Sec  内存限制: 128 MB

    题目描述

    Adam just moved into his new apartment and simply placed everything into it at random. This means in particular that he did not put any effort into placing his electronics in a way that each one can have its own electric socket.
    Since the cables of his devices have limited reach, not every device can be plugged into every socket without moving it first. As he wants to use as many electronic devices as possible right away without moving stuff around, he now tries to figure out which device to plug into which socket. Luckily the previous owner left behind a plugbar which turns one electric socket into 3. 
    Can you help Adam figure out how many devices he can power in total?

    输入

    The input consists of:
    • one line containing three integers m, n and k, where
    – m (1 ≤ m ≤ 1 500) is the number of sockets;
    – n (1 ≤ n ≤ 1 500) is the number of electronic devices;
    – k (0 ≤ k ≤ 75 000) is the number of possible connections from devices to sockets.
    • k lines each containing two integers xi and yi indicating that socket xi can be used to power device yi .
    Sockets as well as electronic devices are numbered starting from 1.
    The plugbar has no cable, i.e. if it is plugged into a socket it simply triples it.

    输出

    Output one line containing the total number of electrical devices Adam can power.

    样例输入

    3 6 8
    1 1
    1 2
    1 3
    2 3
    2 4
    3 4
    3 5
    3 6
    

    样例输出

    5
    

     


    题意 n个插头,m条电线,有一个 一转三的插座,输出最大可连的设备数;

    二分图匹配题;最大匹配数=网络流的最大流;但是一转三的插头,应该通过枚举加一条S到插头点的边,由于图跑一边网络流,就不能再用了,所以要先存起来;

      1 #include<bits/stdc++.h>
      2 #define INF LLONG_MAX/2
      3 #define N 80500
      4 using namespace std;
      5  
      6 struct ss
      7 {
      8     int v,next;
      9     long long flow;
     10 };
     11 int head[N],now_edge=0,S,T;
     12 ss edg[N*10];
     13  
     14 ss lsedg[N*10];
     15 int lshead[N],lssum_edge;
     16 void init() //初始化
     17 {
     18     now_edge=0;
     19     memset(head,-1,sizeof(head)); 
     20 }
     21  
     22 void addedge(int u,int v,long long flow) //加边,加双向边,反向边为0
     23 {
     24     edg[now_edge]=(ss)
     25     {
     26         v,head[u],flow
     27     };
     28     head[u]=now_edge++;
     29     edg[now_edge]=(ss)
     30     {
     31         u,head[v],0
     32     };
     33     head[v]=now_edge++;
     34 }
     35  
     36 int dis[N];
     37  
     38 int bfs() //这个过程给网络分层,避免循环跑;
     39 {
     40     memset(dis,0,sizeof(dis));
     41     queue<int>q;
     42     q.push(S);
     43     dis[S]=1;
     44  
     45     while(!q.empty())
     46     {
     47         int now=q.front();
     48         q.pop();
     49  
     50         for(int i=head[now]; i!=-1; i=edg[i].next)
     51         {
     52             ss &e=edg[i];
     53             if(e.flow>0&&dis[e.v]==0)
     54             {
     55                 dis[e.v]=dis[now]+1;
     56                 q.push(e.v);
     57             }
     58         }
     59     }
     60  
     61     if(dis[T]==0)return 0;
     62     return 1;
     63 }
     64  
     65 int current[N];//就是记录了当前搜索到了这个点的哪一条边
     66 long long dfs(int x,long long maxflow)
     67 {
     68     if(x==T)return maxflow;
     69     for(int i=current[x]; i!=-1; i=edg[i].next)
     70     {
     71         current[x]=i;//然后接下来直接从这个边搜索就行了
     72  
     73         ss &e=edg[i];
     74         if(e.flow>0&&dis[e.v]==dis[x]+1)  //流量大于0,且在下一层
     75         {
     76             long long flow=dfs(e.v,min(maxflow,e.flow)); //在最大流和当前流取较小值
     77  
     78             if(flow!=0)
     79             {
     80                 e.flow-=flow;
     81                 edg[i^1].flow+=flow;
     82                 return flow;
     83             }
     84         }
     85     }
     86     return 0;
     87 }
     88  
     89 long long dinic()
     90 {
     91     long long ans=0,flow;
     92  
     93     while(bfs())
     94     {
     95         for(int i=0; i<N; i++)current[i]=head[i];
     96         while(flow=dfs(S,INF))ans+=flow;
     97     }
     98     return ans;
     99 }
    100  //以上都是板子,用于求最大流
    101 //二分图匹配问题,二分图的每条边权值都是1,二分图最大匹配就是最大流
    102 int main()
    103 {
    104     int m,n,k;
    105     long long  res=0;
    106     scanf("%d%d%d",&m,&n,&k);
    107     init();
    108     S=n+m+1,T=S+1;
    109     for(int i=0; i<k; i++)
    110     {
    111         int u,v;
    112         scanf("%d %d",&u,&v);
    113         addedge(u,v+m,1); //把u,v都变成不重复的数值
    114     }
    115     for(int i=1; i<=m; i++)
    116     {
    117         addedge(S,i,1); //把起点与二分图的一半连起来
    118     }
    119     for(int i=1; i<=n; i++)
    120     {
    121         addedge(i+m,T,1); //与终点连起来
    122     }
    123     long long nowmax=dinic(); //跑一边最大流
    124     long long cancan=0;
    125  
    126     for(int i=0; i<now_edge; i++)  //将图存起来
    127     {
    128         lsedg[i].flow=edg[i].flow;
    129         lsedg[i].next=edg[i].next;
    130         lsedg[i].v=edg[i].v;
    131     }
    132     for(int i=0;i<=n+m+2;i++)lshead[i]=head[i]; 
    133     lssum_edge=now_edge;
    134  
    135     for(int i=1; i<=m; i++) //然后手动把图复制,枚举起点到二分图的点,且权值为2
    136     {
    137         now_edge=lssum_edge;
    138         for(int i=0; i<now_edge; i++)
    139         {
    140             edg[i].flow=lsedg[i].flow;
    141             edg[i].next=lsedg[i].next;
    142             edg[i].v=lsedg[i].v;
    143         }
    144         for(int i=0;i<=n+m+2;i++)head[i]=lshead[i];
    145  
    146         addedge(S,i,2);
    147         long long dangqiancancan=dinic();
    148  
    149         cancan=max(cancan,dangqiancancan);//维护一个最大值
    150     }
    151     printf("%lld
    ",cancan+nowmax);
    152  
    153     return 0;
    154 }
  • 相关阅读:
    一些常用的Unix命令
    Shortcut Blocks with Symbol to_proc 通过to_proc为代码块逻辑命名
    Using with_scope 使用with_scope
    Move Find into Model 将查询方法从控制器上移至模型
    Find Through Association 使用级联查询
    Dynamic find_by Methods 使用动态的find_by方法
    Caching with Instance Variables 缓存与实例变量
    深入浅出object-c
    IT大神进化史-第二章
    IT大神进化史-第一章
  • 原文地址:https://www.cnblogs.com/sylvia1111/p/11398434.html
Copyright © 2020-2023  润新知