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;
}
时间: 2024-08-26 23:17:54

hdu5249 Tricks Device(网络流最大匹配)的相关文章

hdu5249 Tricks Device

分析题意可知: 1.最少需要切断多少边使吴不能找到张(题意吴只能走最短路径上面的边),对从起点到终点的最短路径重新建图,每条边的权值为1,求最大流即可 2.在吴可以找到张的前提下,最多可以切断边的数量:只需要在所有最短路径中寻找一条经过边数量最少的最短路径,用边的总数减去它即可(逆向思维) 代码如下: #include <cstdio> #include <cstring> #include <vector> #include <queue> #define

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

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5294 Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 375    Accepted Submission(s): 98 Problem Description Innocent Wu follows Dumb Zh

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

Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 66    Accepted Submission(s): 14 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the entra

HDU 5294 Tricks Device (最大流+最短路)

题目链接:HDU 5294 Tricks Device 题意:n个点,m条边,并且一个人从1走到n只会走1到n的最短路径,问至少破坏几条边使原图的最短路不存在,最多破坏几条边使原图的最短路劲仍存在 思路: 1.跑一遍最短路,记录下所有最短路径,将这些最短路径的边以(0,1)(流量,容量)加到网络流中,跑一遍最大流 2.记录下的所有最短路径,再加到新的最短路的图中,边权为1,跑一遍最短路,m-最短路 就是答案 注意:有重边的情况 比如: 2 3 1 2 1 1 2 1 1 2 1 ans: 3 2

hdu 5294 Tricks Device(最短路 + 最大流)

hdu 5294 Tricks Device 题目大意:吴邪在古墓中追张起灵,古墓中有很多条路,走每条路都需要一个时间,吴邪只有在最短的时间从古墓的入口到达出口才能追上张起灵.但是张起灵很厉害,他可以使用奇门遁甲使一条路无法通行.现在,问,张起灵最少堵住几条路就可以使吴邪追不上他,以及在吴邪可以追上张起灵的情况下,张起灵最多能堵多少条路. 解题思路:先求出古墓中的最短路(耗时最少的路),再求最短路的同时,记录走最短路要通过哪几条路和走最短路最少通过的路数.最多能堵住的路就是总的路数减去走最短路所

解题报告 之 HDU5294 Tricks Device

解题报告 之 HDU5294 Tricks Device Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the entrance of the tomb while Dumb Zhang's at the end of it. The tomb is made up of many chambers, the total number is N. And there are M c

HDOJ 5294 Tricks Device 最短路(记录路径)+最小割

最短路记录路径,同时求出最短的路径上最少要有多少条边, 然后用在最短路上的边重新构图后求最小割. Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1584    Accepted Submission(s): 388 Problem Description Innocent Wu follows Dumb Z

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

题意:给一个无向图,给起点s,终点t,求最少拆掉几条边使得s到不了t,最多拆几条边使得s能到t 思路: 先跑一边最短路,记录最短路中最短的边数,总边数-最短边数就是第二个答案 第一个答案就是在最短路里面求最小割,也就是求最大流,然后根据最短路在建个新图,权为1,跑一边网络流 模板题,以后就用这套模板了 #include <iostream> #include <cstdio> #include <cstring> #include <queue> #incl

HDU 5294 Tricks Device(多校2015 最大流+最短路啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5294 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the entrance of the tomb while Dumb Zhang's at the end of it. The tomb is made up of many chambers, the total