sgu-301. Boring. Hot. Summer...

Description:

    給你一個 N 個點,M 條邊的無向圖,規定了起點 S 和終點 T ,一個人從點 S 出發去 T ,每一條 ST 的最短路叫做關鍵路徑,屬於關鍵路徑上的點稱爲關鍵點。假設每個單位時間可以移動 1 的長度。對於第 i 個點,如果其不是關鍵點,輸出 “0 ”,否則假設從 Si 時間爲 Ti ,輸出在時間爲 Ti 時,這個人可能在哪些位置上(PS:位置的定義和圖的節點定義不同,不但可以站在節點上,還可以站在邊上,比如一條長度爲7的邊,你可以站在其中長度爲1,2,3,4,5,6 的地方而不僅僅是長度爲 0,7 的兩端)。

   
   
   

Solution:

    首先跑一邊最短路找出哪些點和哪些邊在關鍵路徑上,然後我們對於所有在關鍵路徑上的邊,假設兩個端點爲 u,v(dist[u]<dist[v]) ,那麼我們就把 dist[u]dist[v] 的答案區間加一。
   
   
   

Code:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;

const int Mod=131071;

int N,S,T;
int M;
int dist[2010]={0};
int st=1,en=0;
int num=0;
int hash[2010]={0};
int dui[131100]={0};
int D[2010]={0};
int Sum[2010]={0};
int Sp=0;

struct bian_
{
    int st;
    int to;
    int next;
    int dis;
}bian[400010]={{0,0,0,0}};
int First[2010]={0};
int vis[2010]={0};

void Add(int p,int q,int r,int k)
{
    bian[k].next=First[p];
    bian[k].st=p;
    bian[k].to=q;
    bian[k].dis=r;
    First[p]=k;
    return;
}

void SPFA()
{
    memset(dist,0x3f3f3f3f,sizeof(dist));
    dui[++en]=S;
    dist[S]=0;
    num=1;
    for(;num>0;)
    {
        int u=dui[st];
        st=(st&Mod)+1;
        hash[u]=0;num--;
        for(int i=First[u];i!=0;i=bian[i].next)
        {
            int v=bian[i].to;
            if(dist[v]>dist[u]+bian[i].dis)
            {
                dist[v]=dist[u]+bian[i].dis;
                if(hash[v]==0)
                {
                    hash[v]=1;
                    if(dist[v]<dist[dui[st]])
                    {
                        st=((st+Mod-1)&Mod)+1;
                        dui[st]=v;
                    }
                    else
                    {
                        en=(en&Mod)+1;
                        dui[en]=v;
                    }
                    num++;
                }
            }
        }
    }
    return;
}

int Find(int k)
{
    for(int l=1,r=Sp;l<=r;)
    {
        int mid=(l+r)>>1;
        if(D[mid]==k) return mid;
        if(D[mid]<k) l=mid+1;
        else r=mid-1;
    }
    return 0;
}

int main()
{
    scanf("%d%d%d",&N,&S,&T);
    scanf("%d",&M);
    for(int i=1;i<=M;i++)
    {
        int p,q,r;
        scanf("%d%d%d",&p,&q,&r);
        Add(p,q,r,(i<<1)-1);
        Add(q,p,r,i<<1);
    }
    SPFA();
    for(int i=1;i<=N;i++)
        D[++Sp]=dist[i];
    sort(D+1,D+N+1);
    Sp=1;
    for(int i=2;i<=N;i++)
        if(D[i]!=D[i-1])
            D[++Sp]=D[i];
    for(int i=Sp+1;i<=N;i++) D[i]=0;
    en=1;
    dui[1]=T;
    for(int i=1;i<=en;i++)
    {
        int u=dui[i];
        for(int p=First[u];p!=0;p=bian[p].next)
        {
            int v=bian[p].to;
            if(dist[u]==dist[v]+bian[p].dis)
            {
                int L=Find(dist[v]),R=Find(dist[u]);
                vis[v]=vis[u]=1;
                Sum[L+1]++,Sum[R]--;
                if(hash[v]==0)
                    dui[++en]=v,hash[v]=1;
            }
        }
    }
    for(int i=1;i<=Sp;i++)
        Sum[i]+=Sum[i-1];
    for(int i=1;i<=N;i++)
        if(vis[i]==1)
            Sum[Find(dist[i])]++;
    for(int i=1;i<=N;i++)
    {
        int p=Find(dist[i]);
        printf("%d ",Sum[p]*vis[i]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章