ICPC2019銀川區域賽 H. Delivery Route

鏈接

點擊跳轉

題解

把一個無向圖連通分量看作一個點,然後形成一個DAGDAG,無向圖分量之間用拓撲排序的方法更新,然後無向圖內部使用dijkstradijkstra

dijkstradijkstra的具體過程就是,把那些有值的點放進堆(有值就是說不爲無窮),然後做正常的dijdij

這樣爲啥是對的呢,我覺得可以理解爲有一個超級源,而這個超級源其實就對應原題的SS

代碼

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
struct Graph
{
    int etot, head[maxn], to[maxe], next[maxe], w[maxe];
    void clear(int N)
    {
        for(int i=1;i<=N;i++)head[i]=0;
        etot=0;
    }
    void adde(int a, int b, int c=0){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}
    #define forp(_,__) for(auto p=__.head[_];p;p=__.next[p])
}G1, G2;
struct UnionFind
{
	ll f[maxn], size[maxn];
	void init(ll n)
	{
		for(auto i=1;i<=n;i++)f[i]=i, size[i]=1;
	}
	ll find(ll x){return f[x]==x?x:f[x]=find(f[x]);}
	void merge(ll x, ll y)
    {
        auto fx=find(x), fy=find(y);
        f[fx]=fy;
        if(fx!=fy)size[fy]+=size[fx];
    }
}uf;
ll indeg[maxn];
struct Dijkatra
{
	ll dist[maxn];
	priority_queue<pll,vector<pll>,greater<pll>> heap;
	typedef pair<ll,ll> pr;
    void init(ll N)
    {
        for(ll i=1;i<=N;i++)dist[i]=linf;
    }
	void run(Graph& G, vector<ll>& v)
	{
        for(auto x:v)heap.emplace(pr(dist[x],x));
		while(!heap.empty())
		{
			pr x;
			do x=heap.top(), heap.pop();
			while(x.first!=dist[x.second] and !heap.empty());
			for(auto p=G.head[x.second];p;p=G.next[p])
			{
				if(dist[G.to[p]] > dist[x.second]+G.w[p])
				{
					dist[G.to[p]] = dist[x.second]+G.w[p];
					heap.emplace(pr(dist[G.to[p]],G.to[p]));
				}
			}
		}
	}
}dij;
vector<ll> lis[maxn];
int main()
{
    ll n, x, y, S, i, u, v, w;
    n=read(), x=read(), y=read(), S=read();
    uf.init(n);
    dij.init(n);
    dij.dist[S]=0;
    rep(i,1,x)
    {
        u=read(), v=read(), w=read();
        G1.adde(u,v,w), G1.adde(v,u,w);
        uf.merge(u,v);
    }
    rep(i,1,n)lis[uf.find(i)].emb(i);
    rep(i,1,y)
    {
        u=read(), v=read(), w=read();
        G2.adde(u,v,w);
        indeg[uf.find(v)]++;
    }
    queue<ll> q;
    rep(i,1,n)if(uf.find(i)==i and indeg[i]==0)q.em(i);
    while(!q.empty())
    {
        auto x = q.front(); q.pop();
        dij.run(G1,lis[x]);
        for(auto u:lis[x])
        {
            forp(u,G2)
            {
                auto v=G2.to[p];
                dij.dist[v] = min(dij.dist[v],dij.dist[u]+G2.w[p]);
                indeg[uf.find(v)]--;
                if(indeg[uf.find(v)]==0)q.em(uf.find(v));
            }
        }
    }
    rep(i,1,n)
    {
        if(dij.dist[i]>1e9)printf("NO PATH\n");
        else printf("%lld\n",dij.dist[i]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章