Extended Traffic LightOJ - 1074 (經典SPFA問題)
阿新 • • 發佈:2020-04-21
題目大意:每一個城市都有一定的繁榮度,然後給出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