LightOJ-1074 Extended Traffic (最短路-Bellman_Ford存在負環)
阿新 • • 發佈:2019-01-06
題意:給出t組樣例,每組給出一個n,表示n個點,給出n-1組資料a[]表示每2~n地點上的人流量,下面給出m條路,路的權值為人流公式(a[i]-a[j])^3,故存在負環的情況,題目再給出一個q表示q次詢問,詢問起點1到x點的最短距離.
題解:不能用Dijsktra,只能用Bellman_Ford解決帶負權問題,且它們之間若存在負環或者dis[x]<3 輸出?其餘輸出dis[a].
程式碼如下:
#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<cmath> #include<vector> #include<queue> #include<map> #include<algorithm> using namespace std; #define ll long long #define inf 0x3f3f3f3f const int maxn = 500; struct edge { int u, v, w; edge() {} edge(int uu, int vv, int ww) :u(uu), v(vv), w(ww) {} }; vector<edge> e; int dis[maxn], n; bool vis[maxn], flag[maxn]; int a[maxn]; void Bellman_Ford() { vis[1] = true; for (int k = 1; k<n; k++) //n-1次鬆弛 for (int i = 0; i<e.size(); i++) { edge &p = e[i]; if (vis[p.u] && ((!vis[p.v]) || (dis[p.u] + p.w<dis[p.v]))) { vis[p.v] = true; dis[p.v] = dis[p.u] + p.w; } } for (int i = 0; i<e.size(); i++) { edge &p = e[i]; if (vis[p.u] && ((!vis[p.v]) || (dis[p.u] + p.w<dis[p.v]))) //判斷該點是否還能進行鬆弛,能-》存在負環 flag[p.v] = true; } } void init() { e.clear(); memset(vis, 0, sizeof(vis)); memset(flag, 0, sizeof(flag)); memset(dis, 0, sizeof(dis)); } int main() { int t, m, cas = 1; scanf("%d", &t); while (t--) { init(); printf("Case %d:\n", cas++); scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); scanf("%d", &m); while (m--) //m條有向邊 { int u, v; scanf("%d%d", &u, &v); e.push_back(edge(u, v, (a[v] - a[u])*(a[v] - a[u])*(a[v] - a[u]))); //題目公式 } Bellman_Ford(); scanf("%d", &m); while (m--) { int p; scanf("%d", &p); if (flag[p] || dis[p]<3)printf("?\n"); else printf("%d\n", dis[p]); } } }