hdu 6582(最短路+最小割)


傳送門

題意:

給你一張有向圖,現在你需要刪除一些邊,每次刪除的花費是邊的權值,使得最短路增大,現在問你最小的花費。

題解:

如果要使得最短路增大,顯然是刪掉最短路上的一些邊。我們發現,原圖的最短路也能夠形成一張\(\text{DAG}\),如果我們要使得最短路增大,等價於要求一個最小的花費,使得我們可以破壞這個\(\text{DAG}\),而顯然這個東西就是最小割。因此我們只需要把原圖的最短路建邊,之后在新的圖上跑最小割即可。至於在原圖最短路上建邊,我們只需要對以\(1\)號結點以及\(n\)號結點分別求最短路,之后對於每一條邊所連接的兩個結點\(u\)\(v\),如果\(dis_{1u}+dis_{nv}+val_{uv}=dis_{1n}\)則證明該條邊是最短路上的邊。

看了下數據,看起來好像不太強大啊,為了不T,在這樣的數據量下最好還是得用優秀的最大流算法……

代碼:

#include <bits/stdc++.h>
#define maxn 30005
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
int head1[maxn],cnt1;
int head2[maxn],cnt2;

int n,m;
struct edge{
    int to,next,from;
    long long cost;
}q1[maxn],q2[maxn];
void add_edge(int from,int to,int cost,int *head,int &cnt,edge *q){
    q[cnt].to=to;
    q[cnt].from=from;
    q[cnt].cost=cost;
    q[cnt].next=head[from];
    head[from]=cnt++;
}
typedef pair<int,ll>P;
ll d1[maxn],d2[maxn],e[maxn],h[maxn],cnth[maxn];
void diji(int s,int *head,edge *q,ll *d){
    for(int i=1;i<=n;i++) d[i]=INF;
    priority_queue<P,vector<P>,greater<P> >que;
    d[s]=0;
    que.push(P(0,s));
    while(!que.empty()){
        P p=que.top();
        que.pop();
        int x=p.second;
        if(d[x]<p.first) continue;
        for(int i=head[x];i!=-1;i=q[i].next){
            edge id=q[i];
            if(d[id.to]>d[x]+id.cost){
                d[id.to]=d[x]+id.cost;
                que.push((P(d[id.to],id.to)));
            }
        }
    }
}
//hlpp求解最大流
int head3[maxn],cntt=2;
struct Node{
    int to,next;
    ll val;
}qq[maxn<<1];
int vis[maxn];
int sp,ep;
struct cmp{
    inline bool operator()(int a,int b) const{
        return h[a]<h[b];
    }
};
void addedge(int from,int to,int val){
    qq[cntt].to=to;
    qq[cntt].val=val;
    qq[cntt].next=head3[from];
    head3[from]=cntt++;
}
void add_edge2(int from,int to,int val){
    addedge(from,to,val);
    addedge(to,from,0);
}
void bfs(){
    memset(h,0x3f,sizeof(h));
    h[ep]=0;
    queue<int>que;
    que.push(ep);
    while(!que.empty()){
        int x=que.front();
        que.pop();
        vis[x]=0;
        for(int i=head3[x];i!=-1;i=qq[i].next){
            int to=qq[i].to;
            if(qq[i^1].val&&h[to]>h[x]+1){
                h[to]=h[x]+1;
                if(vis[to]==0){
                    que.push(to);
                    vis[to]=1;
                }
            }
        }
    }
    return;
}
void init(int *head,int &cnt){
    for(int i=0;i<maxn;i++) head[i]=-1;
    memset(vis,0,sizeof(vis));
    memset(cnth,0,sizeof(cnth));
    memset(e,0,sizeof(e));
    cnt=0;
}
priority_queue<int,vector<int>,cmp>Q;
inline void push_(int x){
    for(int i=head3[x];i!=-1;i=qq[i].next){
        int to=qq[i].to;
        if(qq[i].val&&h[to]+1==h[x]){
            int mi=min(qq[i].val,e[x]);
            qq[i].val-=mi;
            qq[i^1].val+=mi;
            e[x]-=mi;
            e[to]+=mi;
            if(vis[to]==0&&to!=ep&&to!=sp){
                Q.push(to);
                vis[to]=1;
            }
            if(e[x]==0)break;
        }
    }
}
inline void relabel(int x){
    h[x]=INF;
    for(int i=head3[x];i!=-1;i=qq[i].next){
        int to=qq[i].to;
        if(qq[i].val&&h[to]+1<h[x]){
            h[x]=h[to]+1;
        }
    }
}
ll hlpp(){
    register int i;
    bfs();
    if(h[sp]==INF)return 0;
    h[sp]=n;
    for(i=1;i<=n;i++)if(h[i]<INF)cnth[h[i]]++;
    for(i=head3[sp];i!=-1;i=qq[i].next){
        int to=qq[i].to;
        ll mi=qq[i].val;
        if(mi){
            e[sp]-=mi;
            e[to]+=mi;
            qq[i].val-=mi;
            qq[i^1].val+=mi;
            if(to!=ep&&vis[to]==0&&to!=sp){
                Q.push(to);
                vis[to]=1;
            }
        }
    }
    while(!Q.empty()){
        int x=Q.top();
        vis[x]=0;
        Q.pop();
        push_(x);
        if(e[x]){
            cnth[h[x]]--;
            if(cnth[h[x]]==0){
                for(int i=1;i<=n;i++){
                    if(i!=sp&&i!=ep&&h[i]>h[x]&&h[i]<n+1){
                        h[i]=n+1;
                    }
                }
            }
            relabel(x);
            cnth[h[x]]++;
            Q.push(x);
            vis[x]=1;
        }
    }
    return e[ep];
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        init(head1,cnt1);
        init(head2,cnt2);
        init(head3,cntt);
        cntt=2;
        for(int i=1;i<=m;i++){
            int from,to,cost;
            scanf("%d%d%d",&from,&to,&cost);
            add_edge(from,to,cost,head1,cnt1,q1);
            add_edge(to,from,cost,head2,cnt2,q2);
        }
        diji(1,head1,q1,d1);
        diji(n,head2,q2,d2);
        if(d1[n]==INF){
            puts("0");
            continue;
        }
        sp=1,ep=n;
        for(int i=1;i<=n;i++){
            for(int j=head1[i];j!=-1;j=q1[j].next){
                int to=q1[j].to;
                int from=q1[j].from;
                int val=q1[j].cost;
                if(d1[from]+d2[to]==d1[n]-val){
                    add_edge2(from,to,val);
                }
            }
        }
        printf("%lld\n",hlpp());
    }
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM