The input contains multiple test cases. The first line of each case is an integer N (2<=N<=600), representing the number of cities in the country. The second line contains one integer M (0<=M<=10000), which is the number of roads. The following M lines are the information of the roads. Each line contains three integers A, B and T, which means the road between city A and city B will cost time T. T is in the range of [1,500]. Next part contains N integers, which are either 1 or 2. The i-th integer shows the supporting leader of city i. To simplify the problem, we assume that Mr. M starts from city 1 and his target is city 2. City 1 always supports leader 1 while city 2 is at the same side of leader 2. Note that all roads are bidirectional and there is at most 1 road between two cities. Input is ended with a case of N=0.
For each test case, output one integer representing the minimum time to reach home. If it is impossible to reach home according to Mr. M's demands, output -1 instead.
2 1 1 2 100 1 2 3 3 1 2 100 1 3 40 2 3 50 1 2 1 5 5 3 1 200 5 3 150 2 5 160 4 3 170 4 2 170 1 2 2 2 1 0
100 90 540
#include <iostream>
#include <fstream>
using namespace std;
#define INF 9999999
const int maxn = 610;
const int maxm = 10010;
int n;
int G[maxn][maxn];
int leader[maxn];
void floyd(){
for(int k = 1; k <= n; ++k){
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
if(G[i][j] > G[i][k] + G[k][j]){
G[i][j] = G[i][k] + G[k][j];
}
}
}
}
}
int main(){
int m, a, b, c;
// freopen("a.txt", "r", stdin);
while(cin >> n >> m && n != 0){
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
if(i == j) G[i][j] = 0;
G[i][j] = INF;
}
}
for(int i = 0; i < m; ++i){
cin >> a >> b >> c;
if(G[a][b] > c){
G[a][b] = G[b][a] = c; //20%的未通过案例来自这句
}
}
for(int i = 1; i <= n; ++i){
cin >> leader[i];
}
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
//只要把不在一个阵营的边设置成有向边即可:leader1->deader2通,leader2->leader1不通
if(leader[i] == 2 && leader[j] == 1){
G[i][j] = INF;
}
}
}
floyd();
if(G[1][2] == INF) cout << "-1" << endl;
else cout << G[1][2] << endl;
}
return 0;
}
/*一开始没读懂题目,不明白那行1212之类的是干嘛的,后来才看见题目中有个最多只能转变1次阵营的限制 ,由题意可知,M出发地是1号,目的地总是2号,从1-2必须转变一次阵营,所以就要求在这之前不能出现2-1的 情况,出现了就不符合题目的要求,所以就在Dijkstra中判断松弛条件的时候加一个判断语句就能求解了*/ #include <bits/stdc++.h> using namespace std; const int MAXN = 601; const int INF = 0x3f3f3f3f; struct Edge{ int to; int length; Edge(int t, int l): to(t), length(l) {} }; struct Point{ int number; int distance; Point(int n, int d): number(n), distance(d) {} bool operator< (const Point& p) const{ return distance > p.distance; } }; vector<Edge> g[MAXN]; int dis[MAXN]; int arr[MAXN]; void Dijkstra(int s){ //优先队列优化的Dijkstra算法 priority_queue<Point> PQ; dis[s] = 0; PQ.push(Point(s, dis[s])); while(!PQ.empty()){ int u = PQ.top().number; PQ.pop(); for(int i = 0; i < g[u].size(); ++i){ int v = g[u][i].to; int l = g[u][i].length; if(!(arr[u-1] == 2 && arr[v-1] == 1) && (dis[v] > dis[u] + l)){ dis[v] = dis[u] + l; PQ.push(Point(v, dis[v])); } } } } int main(){ int n, m; while(cin >> n && n){ cin >> m; memset(g, 0, sizeof(g)); memset(dis, 0x3f, sizeof(dis)); for(int i = 0; i < m; ++i){ int from, to, length; cin >> from >> to >> length; g[from].push_back(Edge(to, length)); g[to].push_back(Edge(from, length)); } for(int i = 0; i < n; ++i){ cin >> arr[i]; } Dijkstra(1); if(dis[2] == INF){ cout << "-1" << endl; } else{ cout << dis[2] << endl; } } return 0; }
//============================================================================ // Name : 2017-06-20-02.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int INF = 1000000000; int G[601][601]; bool vis[601]; int d[601]; int camp[601]; int n,m; int sCamp,tCamp; void dijkstra(int S, int T){ d[S] = 0; vis[S] = true; for(int i=1;i<=n;i++){ if(G[S][i]!=INF){ d[i] = G[S][i]; } } for(int i=1;i<=n;i++){ int _u = -1; int minD = INF; int _i; //找到距离S最小 未被访问的点 for(_i=1;_i<=n;_i++){ if(vis[_i]==false && d[_i]<minD){ _u = _i; minD = d[_i]; } } //不连通 或 已找到目标 返回 if(_u==-1 || _u==T){ return; } vis[_u] = true; // 更新距离 for(_i=1;_i<=n;_i++){ //未被访问 && !(camp[_u]==2&&camp[_i]==1) && 过_u能使距离减小 if(vis[_i]==false && !(camp[_u]==tCamp&&camp[_i]!=tCamp) && d[_u]+G[_u][_i]<d[_i]){//&& !(camp[_u]==2&&camp[_i]==1) d[_i] = d[_u]+G[_u][_i]; } } } } int main() { while(1){ fill(G[0],G[0]+601*601,INF); fill(vis,vis+601, false); fill(d,d+601,INF); scanf("%d",&n); if(n==0){ break; } scanf("%d",&m); for(int i=0;i<m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); if(c<G[a][b]){ G[a][b] = c; G[b][a] = c; } } for(int i=1;i<=n;i++){ int a; scanf("%d",&a); camp[i]=a; } sCamp = camp[1]; tCamp = camp[2]; dijkstra(1,2); if(d[2]==INF){ printf("-1\n"); }else{ printf("%d\n",d[2]); } } return 0; }
/* 很显然因为1,2两人必不是一个阵营的,所以题中说最多经过一条不是同一阵营的边, 那么必须是要经过一条的 !!!知道了必须要经过一条之后,因为题目中最多有1e4条边,点很少, 可以考虑用dijksta先求出1 2 到各自阵营的最短距离,然后枚举那条不是同一阵 营的边维护答案的最小值即可, */ #include<bits/stdc++.h> #define inf 0x3f3f3f3f #define pb push_back #define mk make_pair using namespace std; const int maxm = 1e4+5; const int maxn = 6e2+5; int n,m; int book[maxn]; vector<int>v1,v2; vector<pair<int,int> >edge[maxn]; int d1[maxn],d2[maxn]; void dij1() { bool vis[maxn]; for(int i = 0;i < maxn;++i) { vis[i] = 0; d1[i] = inf; } d1[1] = 0; for(int i = 0;i < v1.size();++i) { int mi = inf,u = -1; for(int j = 0;j < v1.size();++j) { int v = v1[j]; if(vis[v]) continue; if(mi > d1[v]) { mi = d1[v],u = v; } } if(u == -1) break; vis[u] = 1; for(int j = 0;j < edge[u].size();++j) { int to = edge[u][j].first; int cos = edge[u][j].second; if(book[to] == 2) continue; if(d1[to] > d1[u] + cos) { d1[to] = d1[u] + cos; } } } return ; } void dij2() { bool vis[maxn]; for(int i = 0;i < maxn;++i) { d2[i] = inf; vis[i] = 0; } d2[2] = 0; for(int i = 0;i < v2.size();++i) { int mi = inf,u = -1; for(int j = 0;j < v2.size();++j) { int v = v2[j]; if(vis[v]) continue; if(mi > d2[v]) { mi = d2[v],u = v; } } if(u == -1) continue; vis[u] = 1; for(int j = 0;j < edge[u].size();++j) { int to = edge[u][j].first; int cos = edge[u][j].second; if(book[to] == 1) continue; if(d2[to] > d2[u] + cos) { d2[to] = d2[u] + cos; } } } return ; } int main() { while(~scanf("%d",&n)) { memset(book,0,sizeof book); if(n == 0) break; scanf("%d",&m); v1.clear(),v2.clear(); v1.pb(1),v2.pb(2); for(int i = 0;i < maxn;++i) edge[i].clear(); for(int i = 0;i < m;++i) { int a,b,c; scanf("%d %d %d",&a,&b,&c); edge[a].pb(mk(b,c)); edge[b].pb(mk(a,c)); } for(int i = 1;i <= n;++i) { int x; scanf("%d",&x); book[i] = x; if(x == 1) v1.pb(i); if(x == 2) v2.pb(i); } dij1(),dij2(); int mi = inf; for(int i = 0;i < v1.size();++i) { int u = v1[i]; for(int j = 0;j < edge[u].size();++j) { int to = edge[u][j].first; int cos = edge[u][j].second; if(book[u] == book[to]) continue; mi = min(mi,cos + d1[u] + d2[to]); } } /*for(int i = 0;i < v1.size();++i) printf("%d %d\n",v1[i],d1[v1[i]]); puts("debug"); for(int i = 0;i < v2.size();++i) printf("%d %d\n",v2[i],d2[v2[i]]);*/ if(mi == inf) puts("-1"); else printf("%d\n",mi); } return 0; }
#include<stdio.h> #include<vector> #define N 601 #define M 10001 using namespace std; struct E{ int next; int time; }; vector<E> edge[M]; bool mark[N]; int dis[N]; int leader[N]; bool cmp(E a,E b){ return a.time<b.time; } int main(){ int m,n; while(scanf("%d",&n)!=EOF&&n!=0){ scanf("%d",&m); int i,j; int a,b,t; for(i=1;i<=N;i++) edge[i].clear(); while(m--){ scanf("%d%d%d",&a,&b,&t); E tmp; tmp.time=t; tmp.next=b; edge[a].push_back(tmp); tmp.next=a; edge[b].push_back(tmp); } for(i=1;i<=n;i++){ mark[i]=false; dis[i]=-1; scanf("%d",&leader[i]); } int newP=1; dis[1]=0; mark[1]=true; int next,time; for(i=1;i<n;i++){ for(j=0;j<edge[newP].size();j++){ next=edge[newP][j].next; time=edge[newP][j].time; if(leader[newP]==2&&leader[next]==1||mark[next]==true) continue; if(dis[next]==-1||dis[next]>dis[newP]+time){ dis[next]=dis[newP]+time; } } int min=123123123; for(j=1;j<=n;j++){ if(mark[j]!=true&&dis[j]!=-1&&dis[j]<min){ min=dis[j]; newP=j; } } mark[newP]=true; } printf("%d\n",dis[2]); } return 0; }
说好的,两个城市之间只有至多一条路的呢?(你仿佛在逗我,假装有表情包) import java.util.Scanner; /* * QQ: 825580813(一起来敲代码) * 思路: * 1,最短路径的修改版 * 2,添加一个标记数组,判断走到当前城市是否已经穿越了两个阵营 */ public class IWannaGoHome { static int n, m; static int[][] graph; static int[] camp; static final int max = 1000000; public static void main(String[] args) { Scanner sc = new Scanner(System.in); while ((n = sc.nextInt()) != 0) { m = sc.nextInt(); graph = new int[n][n]; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { graph[i][j] = i != j ? max : 0; } } for (int i = 0; i < m; ++i) { int start = sc.nextInt(); int end = sc.nextInt(); int time = sc.nextInt(); if (time < graph[start - 1][end - 1]) { graph[start - 1][end - 1] = graph[end - 1][start - 1] = time; } } camp = new int[n]; for (int i = 0; i < n; ++i) { camp[i] = sc.nextInt(); } int res = getMinTime(); System.out.println(res); } sc.close(); } private static int getMinTime() { int[] minTime = new int[n]; // 最少花费时间 boolean[] flag = new boolean[n]; // 是否穿过两个阵营 boolean[] walked = new boolean[n];// 该城市是否走过 for (int i = 1; i < n; ++i) { minTime[i] = max; } minTime[0] = 0; int start = 0; int curMin = max; for (int i = 0; i < n; ++i) { curMin = max; for (int j = 0; j < n; ++j) { if (!walked[j] && curMin > minTime[j]) { curMin = minTime[j]; start = j; } } walked[start] = true; if (start == 1) { return curMin; } for (int j = 0; j < n; ++j) { if (!walked[j] && curMin + graph[start][j] < minTime[j]) { if (flag[start]) { //如果走到start城市已经穿越了两个阵营 if (camp[start] == camp[j]) { //只能走与start相同的阵营 minTime[j] = curMin + graph[start][j]; flag[j] = true; //并且j阵营也被纳入已穿越的阵营 } } else { //如果走到start城市还没穿越了两个阵营 minTime[j] = curMin + graph[start][j]; //那么都可以走到j城市 if (camp[start] != camp[j]) { //如果start与j的阵营不同, flag[j] = true; //那么j阵营就被纳入穿越的阵营 } } } } } return minTime[1] == max ? -1 : minTime[1]; } }
#include <cstdio> #include <iostream> #include <climits> #include <vector> using namespace std; class adjListGraph{ private: struct edgeNode{ int end; int weight; edgeNode *next; edgeNode(int e,int w,edgeNode *n):end(e),weight(w),next(n){}; }; struct verNode{ int ver; edgeNode *head; verNode(edgeNode *h=NULL):head(h){}; }; int Vers,Edges; verNode *verList; public: adjListGraph(int v):Vers(v),Edges(0){ verList = new verNode[Vers]; } ~adjListGraph(){}; void insert(int x,int y,int w); void dijkstra(int start, int end); }; void adjListGraph::insert(int x,int y,int w){ verList[x].head = new edgeNode(y,w,verList[x].head); Edges++; } void adjListGraph::dijkstra(int start, int end){ int *dis = new int[Vers]; int *prev = new int[Vers]; bool *known = new bool[Vers]; edgeNode *p; int min,u; for(int i = 0; i < Vers; i++){ dis[i] = INT_MAX; known[i] = false; } dis[start] = 0; prev[start] = start; for(int i = 0; i < Vers; i++){ min = INT_MAX; for(int j = 0; j < Vers; j++){ if(!known[j] && dis[j] < min){ min = dis[j]; u = j; } } known[u] = true; for(p = verList[u].head; p!=NULL; p=p->next){ if(!known[p->end] && dis[p->end] > min + p->weight){ dis[p->end] = min + p->weight; prev[p->end] = u; } } } if(dis[end] == INT_MAX) printf("-1\n"); else printf("%d\n", dis[end]); } struct edge{ int begin; int end; int weight; edge(int a, int b, int w):begin(a),end(b),weight(w){}; }; int main(){ int n,m; while(scanf("%d\n", &n) != EOF){ if(n == 0) return 0; vector<edge> vt; adjListGraph G(n); scanf("%d\n", &m); for(int i = 0; i < m; i++){ int x,y,w; scanf("%d%d%d\n",&x,&y,&w); vt.push_back(edge(x-1,y-1,w)); } int *camp = new int[n]; for(int i = 0; i < n; i++){ scanf("%d",&camp[i]); } for(vector<edge>::iterator it=vt.begin(); it!=vt.end(); it++){ if(camp[it->begin] == camp[it->end]){ G.insert(it->begin,it->end,it->weight); G.insert(it->end,it->begin,it->weight); } else if(camp[it->begin] == 1){ G.insert(it->begin,it->end,it->weight); } else{ G.insert(it->end,it->begin,it->weight); } } G.dijkstra(0,1); } return 0; }
#include<iostream> #include<vector> #include<queue> using namespace std; struct edge { int end, time; edge(int e, int t) : end(e), time(t) {}; }; struct point { int name, dist,leader; point(int n, int d,int l) :name(n), dist(d),leader(l) {} bool operator<(const point& p)const//用于构造小根堆时比较 { return this->dist > p.dist; } }; void Dijkstra(vector<edge>*& road, vector<point>& city, int& n) { priority_queue<point> PQ;//小根堆,每轮从当前最近的点开始 PQ.push(city[1]);//起点入堆 while (!PQ.empty()) { int current = PQ.top().name; PQ.pop(); for (unsigned int i = 0; i < road[current].size(); i++)//检查起点是current的边 { edge temp = road[current][i]; int end = temp.end; int cost = temp.time + city[current].dist; //不能改变两次阵营 if (city[current].leader == 2 && city[end].leader == 1) continue; //如果从current到达end的时间比之前路径到达end的时间短,就走这条路 if (cost < city[end].dist) { city[end].dist = cost; PQ.push(city[end]); } } } } int main() { int n, m; while (cin >> n && n != 0) { vector<edge>* road = new vector<edge>[n + 1];//1~n,向量数组模拟邻接表 cin >> m; for (int i = 0; i < m; i++)//输入道路 { int s, e, t; cin >> s >> e >> t; road[s].push_back(edge(e, t)); road[e].push_back(edge(s, t));//无向边,将反向也存进去便于操作 } vector<point> city; city.push_back(point(0, 0xfffffff, 0));//占住city[0]位,便于后面操作 for (int i = 1; i <= n; i++)//输入city { int l; cin >> l; city.push_back(point(i, 0xfffffff, l));//初始都设为不可达 } city[1].dist = 0;//起点到自己的距离为0 Dijkstra(road, city, n); if (city[2].dist == 0xfffffff) cout << -1 << endl; else cout << city[2].dist << endl; city.clear(); } return 0; }
#include <bits/stdc++.h> using namespace std; const int MAXN=605; const int INF=INT_MAX/10; struct Edge{ int to; int length; Edge(int t,int l):to(t),length(l){} }; vector<Edge>graph[MAXN]; int dis[MAXN]; int flag[MAXN]; struct Point{ int num; int distance; int time;//记录每个点从头开始变化的次数 Point(int n,int d,int t):num(n),distance(d),time(t){} bool operator<(const Point& c)const{ return distance>c.distance; } }; void Dijikstra(int x) { int change=0; dis[x]=0; priority_queue<Point>myqueue; myqueue.push(Point(x,dis[x],0)); while(!myqueue.empty()) { Point T=myqueue.top(); int u=myqueue.top().num; myqueue.pop(); for(int i=0;i<graph[u].size();i++) { int v=graph[u][i].to; int l=graph[u][i].length; Point next=T; //每一次进入,都是基于上一个状态的值的变化,是先保存后,不断更新的. if(dis[v]>dis[u]+l) { if(flag[v]!=flag[u]) next.time++; if(next.time<=1) { dis[v]=dis[u]+l; myqueue.push(Point(v,dis[v],next.time)); } } } } return ; } int main() { int n,m; while(cin>>n>>m) { memset(graph,0,sizeof(graph)); fill(dis,dis+n+1,INF); memset(flag,0,sizeof(flag)); for(int i=1;i<=m;i++) { int from,to,length; scanf("%d%d%d",&from,&to,&length); graph[from].push_back(Edge(to,length)); graph[to].push_back(Edge(from,length)); } for(int i=1;i<=n;i++)//归属部落 { int x; cin>>x; flag[i]=x; } Dijikstra(1); if(dis[2]==INF) cout<<-1<<endl; else cout<<dis[2]<<endl; } return 0; }
#include<iostream> (720)#include<cstring> #include<queue> (789)#include<algorithm> #include<cstdio> (802)#include<vector> #include<limits.h> (1124)#define INF INT_MAX using namespace std; struct City{ int to; int len; City(int y,int l):to(y),len(l){} bool operator< (const City& other)const { return len>other.len; } }; vector<City> G[601]; int leader[601]; int dis[601]; int N,M; //N是城市数目,M是道路数目 void Dijstral(){ dis[1]=0; priority_queue<City> myQueue; myQueue.push(City(1,0)); while(!myQueue.empty()){ int u=myQueue.top().to; myQueue.pop(); for(int i=0;i<(int)G[u].size();i++){ int v=G[u][i].to; if(!(leader[v]==1&&leader[u]==2)&&dis[v]>dis[u]+G[u][i].len){ dis[v]=dis[u]+G[u][i].len; myQueue.push(City(v,dis[v])); } } } } int main(){ while(scanf("%d%d",&N,&M)!=EOF){ if(N==0) break; memset(G,0,sizeof(G)); fill(dis+1,dis+1+N,INF); int x,y,len; for(int i=0;i<M;i++){ scanf("%d%d%d",&x,&y,&len); G[x].push_back(City(y,len)); G[y].push_back(City(x,len)); } for(int i=1;i<=N;i++) scanf("%d",&leader[i]); Dijstral(); if(dis[2]!=INF) printf("%d\n",dis[2]); else printf("-1\n"); } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<climits> #include<queue> using namespace std; const int MAXN = 605, MAXM = 20005, INF = INT_MAX; struct enode { int from, to, dis, op = 0; enode(int f = -1, int t = -1, int d = -1) :from(f), to(t), dis(d) {} }road[MAXM]; struct vnode { int num, dis; vnode(int n, int d) :num(n), dis(d) {} bool operator<(vnode x) const { return dis < x.dis; } }; vector<enode> graph[MAXN]; int dis[MAXN], cost[MAXN], camp[MAXN]; void Dijkstra(int s) { //在标准Dijksta上多加了一个cost数组,与dis数组类似一并维护 priority_queue<vnode> que; que.push(vnode(s, 0)); cost[s] = 0; dis[s] = 0; while (!que.empty()) { int p = que.top().num; que.pop(); for (int i = 0; i < graph[p].size(); i++) { int t = graph[p][i].to, d = graph[p][i].dis, c = graph[p][i].op; if (cost[p] + c > 1 || dis[t] < dis[p] + d) continue; dis[t] = dis[p] + d; //两种情况下跳过该边:cost大于1或比已有路径更长 cost[t] = cost[p] + c; //更新dis[t] 和 cost[t] que.push(vnode(t, dis[t])); } } } int main() { int n, m, a, b, c; while (scanf("%d", &n) != EOF) { if (!n) break; int edgeNum = 0; memset(graph, 0, sizeof(graph)); fill(dis, dis + n + 1, INF); fill(cost, cost + n + 1, INF); scanf("%d", &m); for (int i = 0; i < m; i++) { //输入花了点脑筋,还是先储存边然后再更新op值 scanf("%d%d%d", &a, &b, &c); if (a == b) continue; road[edgeNum++] = enode(a, b, c); road[edgeNum++] = enode(b, a, c); } for (int i = 1; i <= n; i++) scanf("%d", &camp[i]); for (int i = 0; i < edgeNum; i++) { int a = road[i].from, b = road[i].to; //若相反阵营则边的op值为1 if (camp[a] != camp[b]) road[i].op = 1; graph[a].push_back(road[i]); } Dijkstra(1); if (cost[2] > 1) dis[2] = -1; //判断cost[2] > 1即可涵盖全部情况 printf("%d\n", dis[2]); } return 0; }
#include <bits/stdc++.h> using namespace std; class Edge { public: int to; int length; Edge(int to, int length) : to(to), length(length) {} // 重载 bool operator==(const Edge &x) { return x.to == to; } }; class Point { public: int number; int distance; Point(int number, int distance) : number(number), distance(distance) {} // 从小到大排列 bool operator<(const Point &p) const { if (distance == p.distance) { return number < p.number; } return distance > p.distance; } }; vector<Edge> graph[605];//邻接表,边用vector存,顶点用数组存 vector<int> Dijkstra(int s, vector<int> camps) { priority_queue<Point> queue; vector<int> dist(605); fill(dist.begin(), dist.end(), INT_MAX); dist[s] = 0; queue.push(Point(s, dist[s])); while (!queue.empty()) { int u = queue.top().number; queue.pop(); for (int i = 0; i < graph[u].size(); ++i) { int v = graph[u][i].to; if (find(camps.begin(), camps.end(), v) != camps.end()) { // 若不是同一阵营,则跳过 int d = graph[u][i].length; if (dist[v] > dist[u] + d) { dist[v] = dist[u] + d; queue.push(Point(v, dist[v])); } } } } return dist; } //先用两次dijkstra算法,分别求出1、2到同阵营各城市的最短路径长度,结果分别存在d1[N]、d2[N]。 //再遍历穿越边境的边,比方说<i, j>穿越边境且i、j分别属于阵营1、阵营2,G[i][j]是i到j的距离, // 那么G[i][j]+d1[i]+d2[j]就是从这条路过境的总路径长度。找出这类路径长度里最短的那条,输出即可 int main() { int n, m; while (cin >> n) { if (n == 0) break; vector<int> camp1; vector<int> camp2; cin >> m; memset(graph, 0, sizeof(graph)); for (int i = 0; i < m; ++i) { int from, to, weight; cin >> from >> to >> weight; if (from == to) continue; // 测试用例里有重边 vector<Edge> ve1 = graph[from]; Edge edge1(to, 0); vector<Edge>::iterator pos1 = find(ve1.begin(), ve1.end(), edge1); // !!!!!!pos1->length = ... 将并不能改变graph中的值!!!!! if (pos1 != ve1.end()) graph[from][pos1 - ve1.begin()].length = min(pos1->length, weight); else graph[from].push_back(Edge(to, weight)); vector<Edge> ve2 = graph[to]; Edge edge2(from, 0); vector<Edge>::iterator pos2 = find(ve2.begin(), ve2.end(), edge2); // !!!!!!pos2->length = ... 将并不能改变graph中的值!!!!! if (pos2 != ve2.end()) graph[to][pos2 - ve2.begin()].length = min(pos2->length, weight); else graph[to].push_back(Edge(from, weight)); } for (int i = 0; i < n; ++i) { int camp = 0; cin >> camp; if (camp == 1) camp1.push_back(i + 1); else camp2.push_back(i + 1); } //先用两次dijkstra算法,分别求出1、2到同阵营各城市的最短路径长度,结果分别存在d1[N]、d2[N]。 vector<int> dist1 = Dijkstra(1, camp1); // 阵营1最短路 vector<int> dist2 = Dijkstra(2, camp2); // 阵营2最短路 vector<pair<int, int>> vp; // 跨阵营1,2的边 的顶点 vector<int> vplen; // 跨阵营1, 2的边的weight //再遍历穿越边境的边,比方说<i, j>穿越边境且i、j分别属于阵营1、阵营2,G[i][j]是i到j的距离, for (int &i : camp1) { vector<Edge> ve = graph[i]; for (int &j : camp2) { Edge edge(j, 0); auto pos = find(ve.begin(), ve.end(), edge); if (pos != ve.end()) { vp.push_back(make_pair(i, j)); vplen.push_back(pos->length); } } ve.clear(); } // 那么G[i][j]+d1[i]+d2[j]就是从这条路过境的总路径长度。找出这类路径长度里最短的那条,输出即可 long long minLen = INT_MAX; for (int i = 0; i < vp.size(); ++i) { if (dist1[vp[i].first] == INT_MAX || dist2[vp[i].second] == INT_MAX) { continue; } if (minLen > dist1[vp[i].first] + dist2[vp[i].second] + vplen[i]) { minLen = dist1[vp[i].first] + dist2[vp[i].second] + vplen[i]; } } if (minLen == INT_MAX) cout << -1 << endl; else cout << minLen << endl; dist1.clear(); dist2.clear(); camp1.clear(); camp2.clear(); vp.clear(); vplen.clear(); } return 0; return 0; }
/*分层图最短路,题目太坑了,说着两城之间最多一条边。数据还有重边,取最小值就行了*/ #include <bits/stdc++.h> #define INF 0x3f3f3f3f3f3f3f3f #define LL long long using namespace std; const int AX = 6e2 + 66 ; int n , m ; int p[AX]; struct Node { int u , num ; LL w ; Node( int u , LL w , int num ):u(u),w(w),num(num) {} bool operator < ( const Node &a )const { return w > a.w ; } }; LL G[AX][AX] ; LL dis[2][AX] ; void djistra() { memset( dis , 0x3f , sizeof(dis) ); dis[1][1] = 0 ; priority_queue<Node>q ; q.push(Node(1,0,1)); while( !q.empty() ) { Node tmp = q.top(); q.pop() ; int u = tmp.u ; int num = tmp.num ; int t = num ; for( int i = 2 ; i <= n ; i++ ) { if( p[i] != p[u] && !num ) continue ; if( G[u][i] < INF ) { if( p[i] != p[u] ) t = 0 ; else t = num ; if( dis[t][i] > dis[num][u] + G[u][i] ) { dis[t][i] = dis[num][u] + G[u][i] ; q.push(Node(i,dis[t][i],t)); } } } } } int main() { int x , y ; LL w ; while( ~scanf("%d",&n) && n ) { memset( G , 0x3f , sizeof(G) ) ; scanf("%d",&m); while( m-- ) { scanf("%d%d%lld",&x,&y,&w); G[x][y] = min( G[x][y] , w ) ; G[y][x] = G[x][y] ; } for( int i = 1 ; i <= n ; i++ ) { scanf("%d",&p[i]); } djistra(); if( dis[0][2] < INF ) printf("%lld\n",dis[0][2]); else printf("-1\n"); } return 0 ; }
有没有大手子可以解释一下为什么会报这种错误:
段错误:您的程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起
#include<iostream>
#define MAX 600
#define INF 10000000
using namespace std;
// N[2, 600] 城市数
// M[0, 10000] 路数
// A B T * M
// leader {1, 2}
int n, G[MAX + 1][MAX + 1];
int d[MAX + 1];
bool vis[MAX + 1] = {false};
int leader[MAX + 1] = {0};
void init(){
int m;
int a, b, t;
for(int i = 0; i < MAX + 1; i++){
for(int j = 0; j < MAX + 1; j++)
G[i][j] = INF;
}
fill(vis, vis + MAX + 1, false);
cin >> m;
for(int i = 1; i <= n; i++){
G[i][i] = 0;
}
for(int i = 0; i < m; i++){
cin >> a >> b >> t;
if(t < G[a][b]){
G[a][b] = t;
G[b][a] = t;
}
}
for(int i = 1; i <= n; i++){
cin >> leader[i];
}
for(int i = 1; i <= n; i++){
for(int j = i; j <= n; j++){
if(leader[i] != leader[j]){
G[i][j] = INF;
}
}
}
}
void Dijkstra(int s){
fill(d, d + MAX + 1, INF);
d[s] = 0;
for(int i = 1; i <= n; i++){
int u = 0;
int MIN = INF;
for(int j = 1; j <= n; j++){
if(vis[j] == false && d[j] < MIN){
u = j;
MIN = d[j];
}
}
if(u == 0) return;
vis[u] = true;
for(int v = 1; v <= n; v++){
if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]){
d[v] = d[u] + G[u][v];
}
}
}
}
int main(){
while(true){
int r1, r2;
cin >> n;
if(n == 0) break;
init();
Dijkstra(1);
r1 = d[2];
Dijkstra(2);
r2 = d[1];
if(r1 == INF && r2 == INF){
cout << "-1" << endl;
}
else{
cout << (r1 < r2 ? r1 : r2) << endl;
}
}
return 0;
}
// test.cpp: 定义控制台应用程序的入口点。//#include "stdafx.h"#include <cstdio>#include <cstdlib>#include <iostream>#include <vector>#include <limits.h>using namespace std;int camp[605];int dist1[605];int dist2[605];bool mark[605];int n, m;struct edge{int next;int c;};vector<edge>e[605];void dijstra(int dist[], int c) {dist[c] = 0;int newP = c;mark[c] = 1;for (int i = 1; i <n; i++) {//遍历n-1次,把其它节点加进来for (int j = 0; j < e[newP].size(); j++) {//拿newP去更新其它不在K中的点int next= e[newP][j].next;if (camp[next]!=c)continue;if (mark[next] == true)continue;if (dist[next] == -1 || dist[next] > dist[newP] + e[newP][j].c) {dist[next] = dist[newP] + e[newP][j].c;}}int min = 123132131;for (int i = 1; i <= n; i++) {if (mark[i])continue;if (camp[i] != c)continue;if (dist[i] == -1)continue;if (dist[i] < min) {min = dist[i];newP = i;}}mark[newP] = 1;}}int getDis(int m, int n) {for (int i = 0; i < e[m].size();i++) {if (e[m][i].next == n) {//cout <<m<< ":" << n<< e[m][i].c << endl;return e[m][i].c;}}return -1;}int isExist(int x, int y) {for (int i = 0; i < e[x].size(); i++) {if (y == e[x][i].next)return i;}return -1;}int main(){//freopen("in.txt", "r", stdin);while (cin >> n&&n) {cin >> m;for (int i = 1; i <= n; i++) {e[i].clear();dist1[i] = -1;dist2[i] = -1;mark[i] = 0;}for (int i = 0; i < m; i++) {int x, y, cost;cin >> x >> y >> cost;edge tmp;tmp.next = y;tmp.c = cost;int ret = isExist(x, y);if (ret == -1) {e[x].push_back(tmp);tmp.next = x;e[y].push_back(tmp);}else {if (e[x][ret].c > cost){e[x][ret].c = cost;ret = isExist(y, x);e[y][ret].c = cost;}}}for (int i = 1; i <= n; i++) {cin >> camp[i];}dijstra(dist1, 1);dijstra(dist2, 2);int min =INT_MAX;int f = min;for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (camp[i] != camp[j]) {if (camp[i] == 1) {if (dist1[i] == -1 || dist2[j] == -1)continue;int d = getDis(i, j);if (d == -1)continue;if (dist1[i] + dist2[j] + d < min) {min = dist1[i] + dist2[j] + d;}}else {if (dist2[i] == -1 || dist1[j] == -1)continue;int d = getDis(i, j);if (d == -1)continue;if (dist2[i] + dist1[j] + d < min) {min = dist2[i] + dist1[j] + d;}}}}}if (min == f)cout << -1 << endl;else cout << min << endl;}return 0;}
谁能告诉我,为什么不过了啊,调试了好多次了
package com.speical.improve;
import java.util.Scanner;
/**
* 带约束的最短路径算法
*
* 为什么就是过不了呢????
* @author special
* @date 2017年12月24日 下午3:40:56
*/
public class Pro27Improve3 {
static final int MAX = 100000000;
static int[][] dis;
static int[] cost, support;
static boolean[] flag;
/**
* 最短路径算法
* 带约束的
*
* @param src
* @param drc
*/
public static void dijkral(int src, int drc){
cost[src] = 0;
int length = support.length;
for(int i = 1; i < length; i++){
int start = -1;
int min = MAX;
for(int j = 1; j < length; j++){
if(!flag[j] && cost[j] < min){
start = j;
min = cost[j];
}
}
if(start == drc || start == -1) return;
flag[start] = true;
for(int k = 1; k < length; k++){
if(!flag[k] && min + dis[start][k] < cost[k]
&& support[k] >= support[start]){
cost[k] = min + dis[start][k];
}
}
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(input.hasNext()){
int n = input.nextInt();
if(n == 0) break;
dis = new int[n + 1][n + 1];
support = new int[n + 1];
flag = new boolean[n + 1];
cost = new int[n + 1];
for(int i = 1; i <= n; i++)
cost[i] = MAX;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
dis[i][j] = MAX;
int roads = input.nextInt();
int src,drc;
while(roads-- > 0){
src = input.nextInt();
drc = input.nextInt();
dis[src][drc] = input.nextInt();
dis[drc][src] = dis[src][drc];
}
for(int i = 1; i <= n; i++){
support[i] = input.nextInt();
}
dijkral(1,2);
System.out.println(cost[2] == MAX ? -1 : cost[2]);
}
}
}
/*跑DJ的时候每个点记录两个值,一个是没有走跨点桥的时候的最短路,一个是走跨点桥的时候的最短路 然后从一个点走到另一个点假如不跨点直接判断能否松弛,否则判断一下当前走跨点桥的机会的用没用, 已经用了的话就不能用了,否则就可以用*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define mod 1000000007 using namespace std; typedef long long ll; const int maxn = 2e5+5; const double esp = 1e-12; const int ff = 0x3f3f3f3f; map<int,int>::iterator it; struct node1 { int to; int w; int ne; } road[30005]; struct node { int pos; int cost; int mk; node(){} node(int pos = 0,int cost = 0,int mk = 0) { this->pos = pos; this->cost = cost; this->mk = mk; } }; int n,m; int len; int head[666]; int dis[2][666]; int num[666]; int vis[2][666]; void add(int f,int to,int w) { road[len].to = to; road[len].w = w; road[len].ne = head[f]; head[f] = len++; } bool operator< (node a,node b) { return a.cost> b.cost; } void dijkstra() { priority_queue<node> q; q.push(node(1,0,0)); dis[0][1] = dis[1][1] = 0; while(!q.empty()) { node t = q.top(); q.pop(); if(vis[t.mk][t.pos]) continue; for(int i = head[t.pos];i!= -1;i = road[i].ne) { int id = road[i].to; if(num[id]!= num[t.pos]) { if(t.mk) continue; if(dis[1][id]> t.cost+road[i].w) { dis[1][id] = t.cost+road[i].w; q.push(node(id,dis[1][id],1)); continue; } } if(t.mk) { if(dis[1][id]> t.cost+road[i].w) { dis[1][id] = t.cost+road[i].w; q.push(node(id,dis[1][id],1)); } } else { if(dis[0][id]> t.cost+road[i].w) { dis[0][id] = t.cost+road[i].w; q.push(node(id,dis[0][id],0)); } } } } if(dis[0][2] == ff&&dis[1][2] == ff) printf("-1\n"); else printf("%d\n",min(dis[0][2],dis[1][2])); } void init() { mem(dis,ff); mem(head,-1); mem(vis,0); len = 0; } int main() { while(~scanf("%d",&n)) { if(n == 0) break; scanf("%d",&m); init(); for(int i = 1;i<= m;i++) { int a,b,c; scanf("%d %d %d",&a,&b,&c); add(a,b,c); add(b,a,c); } for(int i = 1;i<= n;i++) scanf("%d",&num[i]); dijkstra(); } return 0; }