「hdu6582」Path【最短路+最大流】

Path

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 572 Accepted Submission(s): 130

Problem Description

Years later, Jerry fell in love with a girl, and he often walks for a long time to pay visits to her. But, because he spends too much time with his girlfriend, Tom feels neglected and wants to prevent him from visiting her.
After doing some research on the neighbourhood, Tom found that the neighbourhood consists of exactly n n n houses, and some of them are connected with directed road. To visit his girlfriend, Jerry needs to start from his house indexed 1 1 1 and go along the shortest path to hers, indexed n n n.
Now Tom wants to block some of the roads so that Jerry has to walk longer to reach his girl’s home, and he found that the cost of blocking a road equals to its length. Now he wants to know the minimum total cost to make Jerry walk longer.
Note, if Jerry can’t reach his girl’s house in the very beginning, the answer is obviously zero. And you don’t need to guarantee that there still exists a way from Jerry’s house to his girl’s after blocking some edges.

Input

The input begins with a line containing one integer T ( 1 ≤ T ≤ 10 ) T(1\leq T \leq10) T(1T10), the number of test cases.
Each test case starts with a line containing two numbers n , m ( 1 ≤ n , m ≤ 10000 ) n,m(1\leq n,m\leq 10000) n,m(1n,m10000), the number of houses and the number of one-way roads in the neighbourhood.
m lines follow, each of which consists of three integers x , y , c ( 1 ≤ x , y ≤ n , 1 ≤ c ≤ 1 0 9 ) x,y,c(1\leq x,y\leq n,1\leq c\leq10^9) x,y,c(1x,yn,1c109), denoting that there exists a one-way road from the house indexed x x x to y y y of length c c c.

Output

Print T T T lines, each line containing a integer, the answer.

Sample Input

1
3 4
1 2 1
2 3 1
1 3 2
1 3 3

Sample Output

3

Source

2019 Multi-University Training Contest 1

题意

  • 就是给你一张图,每条边都有一个权值,问删去一些边使得最短路径长度变长的最小花费是多少,花费为所有删去的边的权值之和

题解

  • 首先可以 d i j k s t r a dijkstra dijkstra跑出节点1到任意一个点的最短路径,根据这个 d i s dis dis数组可以找出所有可能作为最短路径的边,然后用这些边建一张新的图,显然如果存在从1到n的路径,显然最短路径不会增加,所以相当于求吧这张图一份为 2 2 2的最小代价,很容易想到最小割吧,所以在新建的图上跑 d i n i c dinic dinic就行了
  • 自己的板子只跑了 46 m s 46ms 46ms,在所有提交的当中算是比较快的了

代码

#include<bits/stdc++.h>

using namespace std;
const int maxn=1e5+10;
const int maxm=2e5+10; //注意每条边都有反向边
#define inf 0x3f3f3f3f

namespace IO{ 
    #define BUF_SIZE 100000 
    #define OUT_SIZE 100000 
    #define ll long long 

    bool IOerror=0; 
    inline char nc(){ 
        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; 
        if (p1==pend){ 
            p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); 
            if (pend==p1){IOerror=1;return -1;} 
        } 
        return *p1++; 
    } 
    inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} 
    inline bool read(int &x){ 
        bool sign=0; char ch=nc(); x=0; 
        for (;blank(ch);ch=nc()); 
        if (IOerror) return false; 
        if (ch=='-')sign=1,ch=nc(); 
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 
        if (sign)x=-x; return true;
    } 
    inline bool read(ll &x){ 
        bool sign=0; char ch=nc(); x=0; 
        for (;blank(ch);ch=nc()); 
        if (IOerror) return false; 
        if (ch=='-')sign=1,ch=nc(); 
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 
        if (sign)x=-x; return true;
    } 
    inline bool read(double &x){ 
        bool sign=0; char ch=nc(); x=0; 
        for (;blank(ch);ch=nc()); 
        if (IOerror) return false; 
        if (ch=='-')sign=1,ch=nc(); 
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 
        if (ch=='.'){ 
            double tmp=1; ch=nc(); 
            for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); 
        } 
        if (sign)x=-x; return true;
    } 
    inline bool read(char *s){ 
        char ch=nc(); 
        for (;blank(ch);ch=nc()); 
        if (IOerror) return false; 
        for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; 
        *s=0; return true;
    } 
    inline void read(char &c){ 
        for (c=nc();blank(c);c=nc()); 
        if (IOerror){c=-1;return;} 
    } 
    //fwrite->write 
    struct Ostream_fwrite{ 
        char *buf,*p1,*pend; 
        Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;} 
        void out(char ch){ 
            if (p1==pend){ 
                fwrite(buf,1,BUF_SIZE,stdout);p1=buf; 
            } 
            *p1++=ch; 
        } 
        void print(int x){ 
            static char s[15],*s1;s1=s; 
            if (!x)*s1++='0';if (x<0)out('-'),x=-x; 
            while(x)*s1++=x%10+'0',x/=10; 
            while(s1--!=s)out(*s1); 
        } 
        void println(int x){ 
            static char s[15],*s1;s1=s; 
            if (!x)*s1++='0';if (x<0)out('-'),x=-x; 
            while(x)*s1++=x%10+'0',x/=10; 
            while(s1--!=s)out(*s1); out('\n'); 
        } 
        void print(ll x){ 
            static char s[25],*s1;s1=s; 
            if (!x)*s1++='0';if (x<0)out('-'),x=-x; 
            while(x)*s1++=x%10+'0',x/=10; 
            while(s1--!=s)out(*s1); 
        } 
        void println(ll x){ 
            static char s[25],*s1;s1=s; 
            if (!x)*s1++='0';if (x<0)out('-'),x=-x; 
            while(x)*s1++=x%10+'0',x/=10; 
            while(s1--!=s)out(*s1); out('\n'); 
        } 
        void print(double x,int y){ 
            static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000, 
                1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL, 
                100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL}; 
            if (x<-1e-12)out('-'),x=-x;x*=mul[y]; 
            ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1; 
            ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2); 
            if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i) {}; print(x3);} 
        } 
        void println(double x,int y){print(x,y);out('\n');} 
        void print(char *s){while (*s)out(*s++);} 
        void println(char *s){while (*s)out(*s++);out('\n');} 
        void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}} 
        ~Ostream_fwrite(){flush();} 
    }Ostream; 
    inline void print(int x){Ostream.print(x);} 
    inline void println(int x){Ostream.println(x);} 
    inline void print(char x){Ostream.out(x);} 
    inline void println(char x){Ostream.out(x);Ostream.out('\n');} 
    inline void print(ll x){Ostream.print(x);} 
    inline void println(ll x){Ostream.println(x);} 
    inline void print(double x,int y){Ostream.print(x,y);} 
    inline void println(double x,int y){Ostream.println(x,y);} 
    inline void print(char *s){Ostream.print(s);} 
    inline void println(char *s){Ostream.println(s);} 
    inline void println(){Ostream.out('\n');} 
    inline void flush(){Ostream.flush();}
    #undef ll 
    #undef OUT_SIZE 
    #undef BUF_SIZE 
};
using namespace IO;


long long dis[maxn];int head[maxn],id[maxn],tot,n,m;//id:当前弧优化,即记录可用的最远的那条边
struct node{
    int to,next;long long w;
    node(int a=0,long long b=0,int c=0){
        to=a;w=b;next=c;
    }
}edge[maxm];

void add_edge(int u,int v,long long w)
{
    edge[++tot]=node(v,w,head[u]);
    head[u]=tot;
}

bool bfs(int s,int t)
{
    queue<int> que;que.push(s);
    for(int i=1;i<=n;i++) dis[i]=0,id[i]=head[i];dis[s]=1;  //注意这里的n的范围,不注意经常死循环
    while(!que.empty()){
        int cur=que.front();que.pop();
        for(int i=head[cur];i!=-1;i=edge[i].next){
            int nxt=edge[i].to;
            if(edge[i].w&&!dis[nxt]){
                dis[nxt]=dis[cur]+1;
                que.push(nxt);
                if(nxt==t) return 1;
            }
        }
    }
    return 0;
}

long long dfs(int cur,long long flow,int s,int t)
{
    if(cur==t) return flow;
    long long rest=flow;
    for(int i=id[cur];i!=-1&&rest;i=edge[i].next){
        id[cur]=i;
        if(edge[i].w&&dis[edge[i].to]==dis[cur]+1){
            long long f=dfs(edge[i].to,min(rest,edge[i].w),s,t);
            edge[i].w-=f;
            edge[i^1].w+=f;
            rest-=f;
        }
    }
    return flow-rest;
}

inline long long dinic(int s,int t)
{
    long long  maxflow=0,flow;
    while(bfs(s,t)) while((flow=dfs(s,inf,s,t))) maxflow+=flow;
    return maxflow;
}

struct nod{int v;long long w;};
vector<nod> vec[maxn];

void dijkstra(int s)
{
    priority_queue<pair<long long,int>,vector<pair<long long,int> >,greater<pair<long long,int> > > que;
    memset(dis,0x3f,sizeof(dis));
    dis[s]=0;que.push(pair<long long,int>(0,s));
    while(!que.empty()){
        pair<long long,int> cur=que.top();que.pop();
        if(dis[cur.second]<cur.first) continue;
        for(int i=0;i<vec[cur.second].size();i++){
            nod nxt=vec[cur.second][i];
            if(dis[nxt.v]>dis[cur.second]+nxt.w){
                dis[nxt.v]=dis[cur.second]+nxt.w;
                que.push(pair<long long,int>(dis[nxt.v],nxt.v));
            }
        }
    }
}

void get_graph(int s) //构建最短路图
{
    for(int i=1;i<=n;i++) {
        for(int j=0;j<vec[i].size();j++){
            if(dis[vec[i][j].v]==dis[i]+vec[i][j].w){
                add_edge(i,vec[i][j].v,vec[i][j].w);
                add_edge(vec[i][j].v,i,0);
            }

        }
    }
}

int main()
{
    //freopen("/Users/wzw/Desktop/ACM/1.in","r",stdin);
    int t;read(t);
    while(t--){
        read(n);read(m);
        for(int i=1;i<=n;i++) vec[i].clear(),head[i]=-1;tot=-1;
        for(int i=1,u,v,w;i<=m;i++){
            read(u);read(v);read(w);
            vec[u].push_back(nod{v,w});
        }
        dijkstra(1);
        get_graph(1);
        printf("%lld\n",dinic(1,n));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值