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
/*
很显然因为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;
}
#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;
}
#include <stdio.h>
#include <limits.h>
#define N 601
int G[N][N];//城市间的距离,用时间表示
int camp[N];//各个城市的阵营
int n[3];//n[0]: 城市数量; n[1]、n[2]: 两个阵营各自的城市数量
int Add(int a, int b)
{//两个数相加
if(a==INT_MAX||b==INT_MAX) return INT_MAX;
else return a+b;
}
int Add3(int a, int b, int c)
{//三个数相加
if(a==INT_MAX||b==INT_MAX||c==INT_MAX) return INT_MAX;
else return a+b+c;
}
int d1[N], d2[N];//分别存储1、2到同阵营各点最小距离
bool mark[N];//标记点是否在集合里面
void Dijkstra(int d[N], int from)
{//dijkstra算法求某点到同阵营各点的最小距离
for(int i=0; i<=n[0]; i++)
{//不是同阵营的先塞进集合里面
if(camp[i]==from) mark[i]=false;
else mark[i]=true;
}
mark[from]=true;//把起点塞进集合
for(int i=0; i<=n[0]; i++)//初始化d[N]
{
if(camp[i]==from) d[i]=G[from][i];
}
for(int i=0; i<n[camp[from]]-1; i++)//把同阵营的点全都塞进集合
{
bool isFirst=true;
int near;
for(int i=1; i<=n[0]; i++)//挑一个d[?]最小的,下标为near
{
if(mark[i]==false)
{
if(isFirst)
{
near=i;
isFirst=false;
}
else if(d[i]<d[near]) near=i;
}
}
mark[near]=true;//加入集合
for(int i=1; i<=n[0]; i++)//更新同阵营的点的d[i]信息
{
if(camp[i]==from&&mark[i]==false)
{
int sum=Add(d[near], G[near][i]);
if(sum<d[i]) d[i]=sum;
}
}
}
}
int main()
{
int m;
while(scanf("%d", &n[0])!=EOF)
{
if(n[0]==0) break;
scanf("%d", &m);
for(int i=0; i<=n[0]; i++)//初始化邻接矩阵
{
for(int j=0; j<=n[0]; j++)
{
if(i==j) G[i][j]=0;
else G[i][j]=INT_MAX;
}
}
while(m--)//读取边
{
int a, b, t;
scanf("%d%d%d", &a, &b, &t);
if(t<G[a][b]) G[a][b]=G[b][a]=t;
}
n[1]=n[2]=0;//两个阵营暂时都没城市
for(int i=1; i<=n[0]; i++)//读取阵营信息
{
scanf("%d", &camp[i]);
n[camp[i]]++;
}
Dijkstra(d1, 1);//求出1到同阵营各点的最小距离
Dijkstra(d2, 2);//求出2到同阵营各点的最小距离
int ans=INT_MAX;//先假设最小距离是无穷大
for(int i=1; i<=n[0]; i++)//开始找穿越边境的路
{
for(int j=i+1; j<=n[0]; j++)
{
if(camp[i]==1&&camp[j]==2)//i是1阵营j是2阵营的话
{//看看从这条路过境是否更划算
int sum=Add3(d1[i], d2[j], G[i][j]);
if(sum<ans) ans=sum;
}
else if(camp[i]==2&&camp[j]==1)//反之
{
int sum=Add3(d2[i], d1[j], G[i][j]);
if(sum<ans) ans=sum;
}
}
}
if(ans!=INT_MAX) printf("%d\n", ans);//输出结果
else printf("-1\n");//最短总耗时是无穷,说明无路可走
}
return 0;
} #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;
}