HDU 5294 Tricks Device 2015 Multi-University Training Contest 1 07

22 篇文章 0 订阅
  这题是先跑一个最短路,找最短路中最短的边的个数假设为A,那么第二问的答案为M-A,然后根据最短路的建图,求最小割,也就是把最短路的图建权值为1的边,跑一个最大流,注意重边不要删,因为比赛的时候问的,重边不删。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <math.h>
#define maxn 2000
#define maxm 60000
#define qq 200000
#define inf 1000000005
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;

int heads[maxn + 5], heads2[maxn + 5], que[qq + 5], sizes, sizes2, dp[maxn + 5], dis[maxn + 5], p[maxn + 5], f[maxn + 5][maxn + 5], d[maxn + 5], num[maxn + 5], counts, n, m, mi, ans1, ans2, source, sink;
bool vis[maxn + 5];

struct edge
{
    int v, w, next;
}eg[maxm * 2 + 5], eg2[maxm * 2 + 5];

struct node
{
    int v, t, dis;
};

void inits()
{
    mem(vis, 0);
    mem(heads, -1);
    mem(heads2, -1);
    mem(num, 0);
    sizes = 0;
    sizes2 = 0;
    counts = 0;
    return;
}

void add(int u, int v, int w)
{
    eg[sizes].v = v;
    eg[sizes].w = w;
    eg[sizes].next = heads[u];
    heads[u] = sizes++;
    return;
}

void add2(int u, int v)
{
    eg2[sizes2].v = v;
    eg2[sizes2].w = 1;
    eg2[sizes2].next = heads2[u];
    heads2[u] = sizes2++;
    eg2[sizes2].v = u;
    eg2[sizes2].w = 0;
    eg2[sizes2].next = heads2[v];
    heads2[v] = sizes2++;
    return;
}

void spfa()
{
    mem(vis, 0);
    int top = 0, ta = 0;
    for(int i = 2;i <= n;i++)
        dis[i] = dp[i] = inf;
    dis[1] = 0;
    vis[1] = 0;
    dp[1] = 0;
    que[top++] = 1;
    while(ta != top)
    {
        int u = que[ta++];
        ta %= qq;
        for(int i = heads[u];i != -1;i = eg[i].next)
        {
            int v = eg[i].v;
            int w = eg[i].w;
            if(dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                dp[v] = dp[u] + 1;
                if(!vis[v])
                {
                    vis[v] = 1;
                    que[top++] = v;
                    top %= qq;
                }
            }
            else if(dis[v] == dis[u] + w)
            {
                dp[v] = min(dp[v], dp[u] + 1);
                if(!vis[v])
                {
                    vis[v] = 1;
                    que[top++] = v;
                    top %= qq;
                }
            }
        }
        vis[u] = 0;
    }
    ans1 = m - dp[n];
    return;
}

void build()
{
    for(int i = 1;i <= n;i++)
    {
        for(int j = heads[i];j != -1;j = eg[j].next)
        {
            int v = eg[j].v;
            int w = eg[j].w;
            if(dis[v] - dis[i] == w)
                add2(i, v);
        }
    }
    return;
}

void bfs()
{
    mem(vis, 0);
    d[n] = 0;
    num[d[n]]++;
    int top = 0, ta = 0;
    vis[n] = 1;
    que[top++] = n;
    while(top != ta)
    {
        int u = que[ta++];
        ta %= qq;
        for(int i = heads2[u];i != -1;i = eg2[i].next)
        {
            int v = eg2[i].v;
            if(!vis[v])
            {
                vis[v] = 1;
                d[v] = d[u] + 1;
                num[d[v]]++;
                que[top++] = v;
                top %= qq;
            }
        }
    }
    return;
}

int dfs(int a,int cost)
{
    if(a == sink)
        return cost;
    int mins = n - 1, lv = cost, dd;
    for(int i = heads2[a];i != -1;i = eg2[i].next)
    {
        int v = eg2[i].v;
        int w = eg2[i].w;
        if(w)
        {
            if(d[v] + 1 == d[a])
            {
                if(lv < eg2[i].w)
                    dd = lv;
                else
                    dd = eg2[i].w;
                dd = dfs(v, dd);
                eg2[i].w -= dd;
                eg2[i^1].w += dd;
                lv -= dd;
                if(d[source] >= n)
                    return cost - lv;
                if(!lv)
                    break;
            }
            if(d[v] < mins)
                mins = d[v];
        }
    }
    if(lv == cost)
    {
        --num[d[a]];
        if(num[d[a]] == 0)
            d[source] = n;
        d[a] = mins + 1;
        ++num[d[a]];
    }
    return cost - lv;
}

int isap()
{

    source = 1;
    sink = n;
    int ff = 0, st = source;
    while(d[st] < n)
        ff += dfs(st, inf);
    return ff;
}

int main(int argc, char *argv[])
{
    int a, b, c;
	while(~scanf("%d%d", &n, &m))
    {
        inits();
        for(int i = 0;i < m;i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, c);
            add(b, a, c);
        }
        spfa();
        build();
        bfs();
        ans2 = isap();
        printf("%d %d\n", ans2, ans1);
    }
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值