hdu5249 Tricks Device(网络流最大匹配)

Posted liguangsunls

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu5249 Tricks Device(网络流最大匹配)相关的知识,希望对你有一定的参考价值。

分析题意可知:

1、最少须要切断多少边使吴不能找到张(题意吴仅仅能走最短路径上面的边),对从起点到终点的最短路径又一次建图,每条边的权值为1。求最大流就可以

2、在吴能够找到张的前提下,最多能够切断边的数量:仅仅须要在全部最短路径中寻找一条经过边数量最少的最短路径,用边的总数减去它就可以(逆向思维)

代码例如以下:

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define MAXN 2010
#define INF 1e9+7
using namespace std;
struct Edge
{
    int v,cost,cap;///v代表边的还有一个顶点。cost代表边的代价,cap代表反向边的位置
    Edge(int _v=0,int _cost=0,int _cap=0):v(_v),cost(_cost),cap(_cap) {}
};
vector<Edge> g[MAXN];///保存地图
vector<int> pre[MAXN];///记录最短路径上每一个节点的父节点,用于构建网络流
int flag[MAXN][MAXN];///解决重边问题
int d[MAXN];///记录到达某一点的最短路径所经过的最短的边,用于求解问题2
int dist[MAXN];
struct qnode
{
    int v;
    int c;
    qnode(int _v=0,int _c=0):v(_v),c(_c) {}
    bool operator<(const qnode &r)const
    {
        return c>r.c;
    }
};
int n,m;
int level[MAXN];
void Dijkstra(int s);
void addedge(int u,int v,int w,int cap);
void built(int u);
int DINIC(int s,int t);
int DFS(int now,int maxf,int t);
bool makelevel(int s,int t);
int main()
{
   //FILE* fp = fopen("C:\\Users\\Crazy_Bear\\Desktop\\数据\\data1007\\1007.in","rw");
    while(scanf("%d%d",&n,&m)==2)
    {
        memset(g,0,sizeof(g));
        memset(flag,0,sizeof(flag));
        int x,y,v;
        for(int i=1; i<=m; ++i)
        {
            //fscanf(fp,"%d%d%d",&x,&y,&v);
            scanf("%d%d%d",&x,&y,&v);
            flag[x][y]++;///记录重边的数量
            addedge(x,y,v,0);
            flag[y][x]++;
            addedge(y,x,v,0);
        }
        Dijkstra(1);
        memset(g,0,sizeof(g));
        built(n);///又一次建图
        printf("%d %d\n",DINIC(1,n),m-d[n]);
    }
   // fclose(fp);
    return 0;
}
void addedge(int u,int v,int w,int cap)
{
    g[u].push_back(Edge(v,w,cap));
}
void Dijkstra(int s)
{
    bool vis[MAXN];
    for(int i=1; i<=n; ++i)
    {
        vis[i]=false;
        dist[i]=INF;
        pre[i].clear();
        d[i]=INF;
    }
    priority_queue<qnode> pq;
    while(!pq.empty()) pq.pop();
    dist[s]=0;
    d[s]=0;
    pq.push(qnode(s,0));
    qnode tmp;
    while(!pq.empty())
    {
        tmp=pq.top();
        pq.pop();
        int u=tmp.v;
        if(vis[u]) continue;
        vis[u]=true;
        for(int i=0; i<g[u].size(); ++i)
        {
            int v=g[u][i].v;
            int cost=g[u][i].cost;
            if(dist[v]==dist[u]+cost)
            {
                pre[v].push_back(u);///在求解最短路径的过程中记录父节点
                d[v]=min(d[u]+1,d[v]);
            }
            else if(dist[v]>dist[u]+cost)
            {
                dist[v]=dist[u]+cost;
                pq.push(qnode(v,dist[v]));
                d[v]=d[u]+1;
                pre[v].clear();
                pre[v].push_back(u);
            }
        }
    }
}
void built(int u)
{
    if(u==1)
        return;
    int len=pre[u].size();
    for(int i=0; i<len; ++i)
    {
        if(flag[pre[u][i]][u]>0)
        {
            addedge(pre[u][i],u,1,g[u].size());
            flag[pre[u][i]][u]--;
            addedge(u,pre[u][i],1,g[pre[u][i]].size()-1);
            flag[u][pre[u][i]]--;
            built(pre[u][i]);
        }
    }
}

bool makelevel(int s,int t)
{
    memset(level,0,sizeof(level));
    level[s]=1;
    int que[MAXN];
    int iq=0;
    que[iq++]=s;
    int top;
    for(int i=0; i<iq; ++i)
    {
        top=que[i];
        if(top==t) return true;
        int len=g[top].size();
        for(int i=0; i<len; ++i)
        {
            if(!level[g[top][i].v]&&g[top][i].cost)
            {
                que[iq++]=g[top][i].v;
                level[g[top][i].v]=level[top]+1;
            }
        }
    }
    return false;
}
int DFS(int now,int maxf,int t)
{

    if(now==t) return maxf;
    int ret=0,f;
    int len=g[now].size();
    for(int i=0; i<len; ++i)
    {
        if(g[now][i].cost&&level[g[now][i].v]==level[now]+1)
        {
            f=DFS(g[now][i].v,min(maxf-ret,g[now][i].cost),t);
            g[now][i].cost-=f;
            g[g[now][i].v][g[now][i].cap].cost+=f;
            ret+=f;
            if(ret==maxf) return ret;
        }
    }
    return ret;
}
int DINIC(int s,int t)
{
    int ans=0;
    while(makelevel(s,t)) ans+=DFS(s,INF,t);
    return ans;
}


以上是关于hdu5249 Tricks Device(网络流最大匹配)的主要内容,如果未能解决你的问题,请参考以下文章

2015多校联合训练第一场Tricks Device(hdu5294)

hdu 5294 Tricks Device 最短路建图+最小割

hdu5294 Tricks Device 最短路+最小割 多校联合第一场

划分树 poj2104 hdu5249

HDU5249-KPI(线段树+离散化)

HDU 5249 离线树状数组求第k大+离散化