zoukankan      html  css  js  c++  java
  • 【求出所有最短路+最小割】【多校第一场】【G题】

    题意


    A从1要追在N的 B 只能走最短的路


    问B最少切断多少条路可以让A不能过来

    问B最多切断多少条路A还是能过来


    对于1 求出1到N的所有最短路的路径,对其求最小割 

    对于2 求出长度最小的最短路即可



    如何求所有最短路呢  利用这个

    void dfs(int s,int ans)
    {
    
        if(s==N)
        {
            ANS2=min(ans,ANS2);
            return ;
        }
        for(EDGE *p=Graph[s].first;p;p=p->next)
        {
            if(dist[s]+p->w==dist[p->to])
            {
                if(VISIT[s]==0) { VISIT[s]=1;nn++;}
                if(VISIT[p->to]==0) { VISIT[p->to]=1;nn++;}
                addedge(s,p->to,1,0);
                dfs(p->to,ans+1);
            }
        }
    }
    即这个判断来判断所有路径
     if(dist[s]+p->w==dist[p->to])




    代码如下
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313
    using namespace std;
    const int maxn=5000;
    int visit[maxn];
    int dist[maxn];
    int VISIT[maxn];
    int N,m;
    struct EDGE{
        int w;
        int to;
        EDGE *next;
    }E[300000],*EE;
    struct node{
        EDGE *first;
    }Graph[maxn];
    //网络流
    const int MAXN=4000+5;
    const int MAXM=300000;
    const int INF=0x3f3f3f3f;
    int nn=0;
    int ANS2=0x3f3f3f3f;
    struct Edge
    {
        int to,next,cap,flow;
        void get(int a,int b,int c,int d)
        {
            to=a;next=b;cap=c;flow=d;
        }
    }edge[MAXM];
    int tol;
    int head[MAXN];
    int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
    void init()
    {
        tol=0;
        memset(head,-1,sizeof(head));
    }
    //单向图三个参数,无向图四个参数
    void addedge(int u,int v,int w,int rw=0)
    {
        edge[tol].get(v,head[u],w,0);head[u]=tol++;
        edge[tol].get(u,head[v],rw,0);head[v]=tol++;
    }
    int sap(int start,int end,int N)
    {
        memset(gap,0,sizeof(gap));
        memset(dep,0,sizeof(dep));
        memcpy(cur,head,sizeof(head));
        int u=start;
        pre[u]=-1;
        gap[0]=N;
        int ans=0;
        while(dep[start]<N)
        {
            if(u==end)
            {
                int Min=INF;
                for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                    if(Min>edge[i].cap-edge[i].flow)
                       Min=edge[i].cap-edge[i].flow;
                for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                {
                    edge[i].flow+=Min;
                    edge[i^1].flow-=Min;
                }
                u = start;
                ans+=Min;
                continue;
            }
            bool flag=false;
            int v;
            for(int i=cur[u];i !=-1;i=edge[i].next)
            {
                v=edge[i].to;
                if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
                {
                    flag=true;
                    cur[u]=pre[v]=i;
                    break;
                }
            }
            if(flag)
            {
                u=v;
                continue;
            }
            int Min=N;
            for(int i=head[u];i!=-1;i=edge[i].next)
                if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
            gap[dep[u]]--;
            if(!gap[dep[u]]) return ans;
            dep[u]=Min+1;
            gap[dep[u]]++;
            if(u!=start) u=edge[pre[u]^1].to;
        }
        return ans;
    }
    void Link(int u,int v,int w)
    {
        EE->next=Graph[u].first;EE->to=v;EE->w=w;Graph[u].first=EE++;
    }
    void input()
    {
        ANS2=m;
        memset(E,0,sizeof(E));
        memset(Graph,0,sizeof(Graph));
        EE=E+1;
        int a,b,c;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            Link(a,b,c);
            Link(b,a,c);
        }
    }
    void finddist(int &s)
    {
        int ans=2000000000;
        for(int i=1;i<=N;i++)
        if(visit[i]==0)
        {
            if(dist[i]<ans)
            {
                ans=dist[i];
                s=i;
            }
        }
        visit[s]=1;
    }
    void Dijkstra(int s)
    {
        dist[s]=0;
        for(int k=1;k<=N-1;k++)
        {
            finddist(s);
            for(EDGE *p=Graph[s].first;p;p=p->next)
                if(dist[s]+p->w<dist[p->to]) dist[p->to]=dist[s]+p->w;
        }
    }
    void CSH()
    {
        memset(visit,0,sizeof(visit));
        for(int i=0;i<maxn;i++)
        dist[i]=1000000000;
    }
    void dfs(int s,int ans)
    {
    
        if(s==N)
        {
            ANS2=min(ans,ANS2);
            return ;
        }
        for(EDGE *p=Graph[s].first;p;p=p->next)
        {
            if(dist[s]+p->w==dist[p->to])
            {
                if(VISIT[s]==0) { VISIT[s]=1;nn++;}
                if(VISIT[p->to]==0) { VISIT[p->to]=1;nn++;}
                addedge(s,p->to,1,0);
                dfs(p->to,ans+1);
            }
        }
    }
    void solve()
    {
         nn=0;
         memset(VISIT,0,sizeof(VISIT));
         CSH();
         Dijkstra(1);
          init();
         dfs(1,0);
         printf("%d %d
    ",sap(1,N,nn),m-ANS2);
    }
    int main()
    {
      // freopen("a.in","r",stdin);
      // freopen("a.out","w",stdout);
        while(cin>>N>>m)
        {
            input();
            solve();
        }
    }
    




  • 相关阅读:
    hdu 1042 N!(大数)
    1027代码审计平台 3 Java maven
    1027代码审计平台 2-sonarscanner项目变更
    1027代码审计平台 1-sonar scanner
    app遍历——appCrawler的使用
    markdown语法
    app crawler1
    WebDriverAgent原理
    yaml语言教程
    Air test 基于屏幕比例实现滑动的方法
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480327.html
Copyright © 2011-2022 走看看