码迷,mamicode.com
首页 > 其他好文 > 详细

2019杭电多校训练(一)

时间:2019-07-23 13:41:32      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:add   flow   return   ret   out   删除   sha   c++   can   

比赛链接:

http://acm.hdu.edu.cn/search.php?field=problem&key=2019+Multi-University+Training+Contest+1&source=1&searchmode=source

hdu6582

题意:

删除某些边,让$1$到$n$的最短路径发生变化

删除某条边的费用是边的长度

分析:

先用迪杰斯特拉跑一遍整个图,满足$dis[a]+w=dis[b]$的边,肯定是最短路径上的边

选出这些边,找到一个最小割集,Dinic比EK快很多,虽然渐进复杂度相同,都是$O(nm^2)$

Dinic加上弧优化后速度更快

ac代码(Dinic没有弧优化):

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pa pair<ll,ll>
using namespace std;
const ll maxn=1e4+5;
const ll maxm=1e7+10;
const ll mod=1e9+7;
vector<pair<int,int>>ve[maxn];
ll dis[maxn];
int n,m,edge_num=-1,head[maxn],dep[maxn];
bool vis[maxn];
struct Edge{
    int to,nex,v;
}edge[maxn*2];//maxn=1e4
void add_edge(int a,int b,int c)//边数从0开始,每次加上反向边,这样奇偶交替加边,重边无所谓
{
    edge[++edge_num].to=b;
    edge[edge_num].nex=head[a];
    edge[edge_num].v=c;
    head[a]=edge_num;
}
bool bfs()
{
    for(int i=1;i<=n;i++)dep[i]=1e9;
    dep[1]=0;
    queue<int>que;
    que.push(1);
    while(que.size()){
        int now=que.front();
        que.pop();
        for(int i=head[now];i!=-1;i=edge[i].nex){
            int to=edge[i].to;
            int v=edge[i].v;
            if(v&&dep[to]>dep[now]+1){
                dep[to]=dep[now]+1;
                que.push(to);
            }

        }
    }
    if(dep[n]==1e9)return false;
    else return true;
}
int dfs(int x,int lowflow)
{
    if(x==n||lowflow==0)return lowflow;
    int reslow=0;
    int used=0;
    for(int i=head[x];i!=-1;i=edge[i].nex){
        int to=edge[i].to;
        if(edge[i].v&&dep[x]+1==dep[to]){
            if(reslow=dfs(to,min(lowflow,edge[i].v))){
                edge[i].v-=reslow;
                edge[i^1].v+=reslow;
                used+=reslow;
                lowflow-=reslow;
                if(lowflow<=0)break;
            }
        }
    }
    return used;
}
void Dinic()
{
    ll maxflow=0;
    int lowflow;
    while(bfs()){
        while(lowflow=dfs(1,1e9)){
                maxflow+=lowflow;
        }
    }
    printf("%lld\n",maxflow);
}
void dj()
{
    for(int i=1;i<=n;i++)dis[i]=1e18,vis[i]=false;
    dis[1]=0;
    priority_queue<pair<ll,int>>que;
    que.push(make_pair(0,1));
    while(que.size()){
        pair<ll,int>now=que.top();
        que.pop();
        if(vis[now.second])continue;
        vis[now.second]=true;
        for(int i=0;i<ve[now.second].size();i++){
            int to=ve[now.second][i].first;
            int w=ve[now.second][i].second;
            if(dis[to]>dis[now.second]+w){
                dis[to]=dis[now.second]+w;
                que.push(make_pair(-dis[to],to));
            }
        }
    }
}
int main()
{
//    freopen("D:/a.txt","w",stdout);
//    freopen("D:/2.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            ve[a].push_back(make_pair(b,c));
        }
        dj();
        if(dis[n]==1e18){
            printf("0\n");
            continue;
        }
        for(int i=1;i<=n;i++)head[i]=-1;
        edge_num=-1;
        for(int i=1;i<=n;i++){
            for(int j=0;j<ve[i].size();j++){
                int a=i,b=ve[i][j].first,c=ve[i][j].second;
                if(dis[a]+c==dis[b])add_edge(a,b,c),add_edge(b,a,0);
            }
        }
        Dinic();
        for(int i=1;i<=n;i++)ve[i].clear();
    }
    return 0;
}

 

ac代码(Dinic弧优化):

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pa pair<ll,ll>
using namespace std;
const ll maxn=1e4+5;
const ll maxm=1e7+10;
const ll mod=1e9+7;
vector<pair<int,int>>ve[maxn];
ll dis[maxn];
int n,m,edge_num=-1,head[maxn],dep[maxn],cur[maxn];
bool vis[maxn];
struct Edge{
    int to,nex,v;
}edge[maxn*2];//maxn=1e4
void add_edge(int a,int b,int c)//边数从0开始,每次加上反向边,这样奇偶交替加边,重边无所谓
{
    edge[++edge_num].to=b;
    edge[edge_num].nex=head[a];
    edge[edge_num].v=c;
    head[a]=edge_num;
}
bool bfs()//分层
{
    for(int i=1;i<=n;i++)dep[i]=1e9;
    dep[1]=0;
    queue<int>que;
    que.push(1);
    while(que.size()){
        int now=que.front();
        que.pop();
        for(int i=head[now];i!=-1;i=edge[i].nex){
            int to=edge[i].to;
            int v=edge[i].v;
            if(v&&dep[to]>dep[now]+1){
                dep[to]=dep[now]+1;
                que.push(to);
            }

        }
    }
    if(dep[n]==1e9)return false;
    else return true;
}
int dfs(int x,int lowflow)
{
    if(x==n||lowflow==0)return lowflow;
    int reslow=0;
    int used=0;
    for(int &i=cur[x];i!=-1;i=edge[i].nex){
        int to=edge[i].to;
        if(edge[i].v&&dep[x]+1==dep[to]){
            if(reslow=dfs(to,min(lowflow,edge[i].v))){
                edge[i].v-=reslow;
                edge[i^1].v+=reslow;
                used+=reslow;
                lowflow-=reslow;
                if(lowflow<=0)break;
            }
        }
    }
    return used;
}
void Dinic()
{
    ll maxflow=0;
    int lowflow;
    while(bfs()){
        for(int i=1;i<=n;i++)cur[i]=head[i];
        while(lowflow=dfs(1,1e9)){
                maxflow+=lowflow;
        }
    }
    printf("%lld\n",maxflow);
}
void dj()
{
    for(int i=1;i<=n;i++)dis[i]=1e18,vis[i]=false;
    dis[1]=0;
    priority_queue<pair<ll,int>>que;
    que.push(make_pair(0,1));
    while(que.size()){
        pair<ll,int>now=que.top();
        que.pop();
        if(vis[now.second])continue;
        vis[now.second]=true;
        for(int i=0;i<ve[now.second].size();i++){
            int to=ve[now.second][i].first;
            int w=ve[now.second][i].second;
            if(dis[to]>dis[now.second]+w){
                dis[to]=dis[now.second]+w;
                que.push(make_pair(-dis[to],to));
            }
        }
    }
}
int main()
{
//    freopen("D:/a.txt","w",stdout);
//    freopen("D:/2.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            ve[a].push_back(make_pair(b,c));
        }
        dj();
        if(dis[n]==1e18){
            printf("0\n");
            continue;
        }
        for(int i=1;i<=n;i++)head[i]=-1;
        edge_num=-1;
        for(int i=1;i<=n;i++){
            for(int j=0;j<ve[i].size();j++){
                int a=i,b=ve[i][j].first,c=ve[i][j].second;
                if(dis[a]+c==dis[b])add_edge(a,b,c),add_edge(b,a,0);
            }
        }
        Dinic();
        for(int i=1;i<=n;i++)ve[i].clear();
    }
    return 0;
}

  

2019杭电多校训练(一)

标签:add   flow   return   ret   out   删除   sha   c++   can   

原文地址:https://www.cnblogs.com/carcar/p/11231075.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!