1. 程式人生 > >Extended Traffic LightOJ - 1074 (經典SPFA問題)

Extended Traffic LightOJ - 1074 (經典SPFA問題)

題目大意:每一個城市都有一定的繁榮度,然後給出m條有向邊i->j,定義這條邊的權值為pow(arr[j]-arr[i],3),然後給你q個詢問,每個詢問輸入一個x。

然後問你點1到x的距離,如果小與3或者不可到達,那麼輸出?,否則的話就輸出dis[x]。

題解:如果說這是一個無向圖,那麼如果這個圖記憶體在負環,那麼輸出一定是?,因為點y假設可以到打1,那麼就可以通過負環無限減小到y的距離,這樣的話一定是小於3的。但這是個有向圖,該怎麼操作呢?我們可以把與負環相連線的元素給他打上標記,另外,如果說點z和負環相連,也就沒必要對z進行鬆弛了...

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1e18+7;
const ll N=1e5+7;
struct stu{
    ll to,nxt;
    ll weight;
}edge[N];
ll time1=1;
ll n;
ll cnt=0,head[N];
ll dis[N];
bool mark[N],cir[N];
ll num[N];
ll value[N];
void add(ll x,ll y,ll weight){
    edge[cnt].to=y;
    edge[cnt].weight=weight;
    edge[cnt].nxt=head[x];
    head[x]=cnt++;
}
void dfs(int v){
    cir[v]=1;
    for(int i=head[v];i!=-1;i=edge[i].nxt){
        v=edge[i].to;
        if(!cir[v]) dfs(v);
    }
}
bool spfa(){
    for(ll i=0;i<=n;i++) dis[i]=INF;
    memset(cir,0,sizeof cir);
    memset(mark,0,sizeof mark);
    memset(num,0,sizeof num);
    dis[1]=0;
    queue<ll>que;
    que.push(1);
    num[1]++;
    mark[1]=1;
    while(que.size()){
        ll u=que.front();
        que.pop();
        mark[u]=0;
        for(ll i=head[u];i!=-1;i=edge[i].nxt){
            ll v=edge[i].to;
            if(cir[v]) continue ;
            if(dis[v]>dis[u]+edge[i].weight){
                dis[v]=dis[u]+edge[i].weight;
                if(!mark[v]) {
                    num[v]++;
                    mark[v]=1;
                    que.push(v);
                    if(num[v]>=n) dfs(v);
                }
            }
        }
    }
    return 0;
}
void solve(){
    memset(head,-1,sizeof head); 
    cnt=0;
    cin>>n;
    for(ll i=1;i<=n;i++) cin>>value[i];
    ll m,x,y;
    cin>>m;
    for(ll i=1;i<=m;i++){
        cin>>x>>y;
        add(x,y,(value[y]-value[x])*(value[y]-value[x])*(value[y]-value[x]));
    }
    spfa();
    ll problem;
    cin>>problem;
    ll time=1;
    printf("Case %d:\n",time1++);
    while(problem--){
        ll q;
        cin>>q;
        if(cir[q]||dis[q]<3||dis[q]==INF){
            cout<<"?"<<endl;
        }
        else{
            cout<<dis[q]<<endl;
        }
    }
}
int main(){
    ll t;
    cin>>t;
    while(t--) solve();
    return 0;
}

 

&n