Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (<= 500) - the number of cities (and the cities are numbered from 0 to N-1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively.
It is guaranteed that there exists at least one path from C1 to C2.
For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather.
All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.
5 6 0 2<br/>1 2 1 5 3<br/>0 1 1<br/>0 2 2<br/>0 3 1<br/>1 2 1<br/>2 4 1<br/>3 4 1
2 4
import java.util.Scanner; /** * Emergency (25) * * @author Administrator 牛客通过率只有90% */ public class Main { static int[][] map; // 邻接矩阵,存储所有边 static boolean[] visited; // 标志一个城市是否已经被访问 static int[] dist; // 记录从起点到某点的距离。初始化为Integer.MAX_VALUE static int[] cityTeams;// 记录每个城市的救援队数量 static int maxTeams;// 记录到达每个城市最大救援队数量 static int count; // 记录最短路径数 static int source;// 起点 static int dest;// 重点 static int cityNum;// 城市数量 public static void main(String[] args) { // 初始化 Scanner sc = new Scanner(System.in); cityNum = sc.nextInt(); int edgeNum = sc.nextInt(); source = sc.nextInt(); dest = sc.nextInt(); map = new int[cityNum][cityNum]; visited = new boolean[cityNum]; dist = new int[cityNum]; cityTeams = new int[cityNum]; for (int i = 0; i < cityNum; i++) { cityTeams[i] = sc.nextInt(); } for (int i = 0; i < cityNum; i++) { dist[i] = Integer.MAX_VALUE; for (int j = 0; j < cityNum; j++) { if (i == j) map[i][i] = 0; else map[i][j] = Integer.MAX_VALUE; } } // 边初始化 for (int i = 0; i < edgeNum; i++) { int a = sc.nextInt(), b = sc.nextInt(), L = sc.nextInt(); map[a][b] = L; map[b][a] = L; } sc.close(); dijkstra(source, dest, cityNum); for (int i = 0; i < cityNum; i++) visited[i] = false; dfs(source, cityTeams[source]); System.out.println(count + " " + maxTeams); } private static void dfs(int s, int teamNum) { if (s == dest) { if (teamNum > maxTeams) maxTeams = teamNum; count++; return; } visited[s] = true; for (int i = 0; i < cityNum; i++) { if (!visited[i] && dist[i] == dist[s] + map[s][i]) { visited[i] = true; dfs(i, teamNum + cityTeams[i]); visited[i] = false; } } } private static void dijkstra(int source, int dest, int cityNum) { // dest = 3; dist[source] = 0; int curNode = source; while (true) { // 把当前点加入已遍历集合 if (curNode == -1) break; visited[curNode] = true; for (int i = 0; i < cityNum; i++) { // (map[curNode][i] + dist[curNode] < dist[i])会溢出 if (!visited[i] && map[curNode][i] <= dist[i] - dist[curNode]) { dist[i] = map[curNode][i] + dist[curNode]; } } int min = Integer.MAX_VALUE, index = -1; // 找到当前未放入已遍历集合的路径最小值 for (int i = 0; i < cityNum; i++) { if (!visited[i] && dist[i] < min) { // 如果最小值更新,计数器从0开始重新计数 min = dist[i]; index = i; } } curNode = index; } } }
#include <iostream> #include <vector> #include <algorithm> using namespace std; const int maxn=510; const int INF=10000000; //INF作为“无穷大”即不可能的距离 struct Node{ //边表结点(v为顶点编号,dis为边权值) int v,dis; }; vector<Node> Adj[maxn]; bool vis[maxn]={false}; //d为起点到某点最短路径,num为到某点最短路径条数 int n,m,start,final,d[maxn],num[maxn]={0},weight[maxn],w[maxn]={0}; //weight为某点权值,w为到某点最短路径中点权值和最大 void Dijkstra(int s){ fill(d,d+maxn,INF);d[s]=0; //初始化到各点最短路径长,s为起点,起点到本身路径为0 num[s]=1; //到起点本身的最短路径初始为1条 w[s]=weight[s]; //到起点本身的最短路径点权之和初始即为起点本身权值 for(int i=0;i<n;i++){ int u=-1,min=INF; //初始化 for(int j=0;j<n;j++){ //找到未访问过的结点中d[]最小的 if(vis[j]==false&&d[j]<min){ u=j;min=d[j]; } } if(u==-1) return; //找不到小于INF的d[u],即剩下的结点与起点s不连通 vis[u]=true; for(int j=0;j<Adj[u].size();j++){ int v=Adj[u][j].v; if(vis[v]==false){ //若v未访问过 if(d[u]+Adj[u][j].dis<d[v]){ //若u作为中介点可以使d[v]更优 d[v]=d[u]+Adj[u][j].dis; num[v]=num[u]; //覆盖到v的最短路径条数 w[v]=w[u]+weight[v]; } else if(d[u]+Adj[u][j].dis==d[v]){ //找到一条与最短路径相同长度的路径 num[v]+=num[u]; //直接加上到u的最短路径条数 if(w[v]<w[u]+weight[v]) //若以u为中介点时点权之和更大 w[v]=w[u]+weight[v]; } } } } } int main(){ cin>>n>>m>>start>>final; for(int i=0;i<n;i++) cin>>weight[i]; for(int i=0;i<m;i++){ int id1,id2,dis; Node temp; cin>>id1>>id2>>temp.dis; temp.v=id2;Adj[id1].push_back(temp); //无向图 temp.v=id1;Adj[id2].push_back(temp); } Dijkstra(start); cout<<num[final]<<" "<<w[final]; return 0; }
//PAT和牛客都AC了,有疑问可以评论 #include<iostream> #include<algorithm> #define inf 65535 using namespace std; int n,m,s,t,used[500]={0},cost[500][500],mincost[500],path[500],amount[500],maxget[500]; void dijkstra(int s) { int u,v,i,j; fill(path,path+500,1); mincost[s]=0; while(1) { v=-1; for(u=0;u<n;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=1; for(u=0;u<n;u++) { if(!used[u]&&mincost[u]>mincost[v]+cost[v][u]) { mincost[u]=mincost[v]+cost[v][u]; maxget[u]=maxget[v]+amount[u]; path[u]=path[v]; } else if(!used[u]&&mincost[u]==mincost[v]+cost[v][u]) { path[u]+=path[v]; maxget[u]=max(maxget[u],maxget[v]+amount[u]); } } } } int main() { int i,j,u,v; for(i=0;i<500;i++) for(j=0;j<500;j++) cost[i][j]=inf; cin>>n>>m>>s>>t; for(i=0;i<n;i++) { mincost[i]=inf; cin>>amount[i]; maxget[i]=amount[i]; } for(i=0;i<m;i++) { cin>>u>>v; cin>>cost[u][v]; cost[v][u]=cost[u][v]; } dijkstra(s); cout<<path[t]<<' '<<maxget[t]; return 0; }
我真是服了,这里是正确的,但是pat上测点3过不去,不给测点真是脑壳痛#include<iostream> #include<vector> using namespace std; const int maxCity = 510; const int maxValue = 1000000000; int cityNum, roadNum, cityStart, cityEnd; int teamAmount[maxCity]; struct Node { int number; int value = maxValue; Node(int number, int value) { this->number = number; this->value = value; }}; vector<Node> graph[maxCity]; void stPath(int &pathNumber, int &teamNumber) { pathNumber = 0; teamNumber = 0; bool isFind[maxCity] = { false }; int minPath[maxCity] = { maxValue };//记录最短路径 int minPathNumber[maxCity] = { 0 };//到达某个点最短路径数量 int maxTeamAmount[maxCity] = { 0 }; //赋初值 for (int i = 0; i < cityNum; i++) { minPath[i] = maxValue; } minPath[cityStart] = 0;//起始位置置0; int pathThrough = cityStart;//代表中间节点 isFind[cityStart] = true; minPathNumber[cityStart] = 1;//防止更新后永远为0; maxTeamAmount[cityStart] = teamAmount[cityStart]; for (int i = 0; i < cityNum - 1; i++)//外层循环结束时所有最小路径找到 { //更新所有节点 for (auto iter = graph[pathThrough].begin(); iter != graph[pathThrough].end(); iter++) { if (isFind[iter->number] == false) { if (iter->value + minPath[pathThrough] < minPath[iter->number])//如果经过中间节点可以更短,则更新最小值和路径数量 { minPath[iter->number] = iter->value + minPath[pathThrough]; minPathNumber[iter->number] = minPathNumber[pathThrough]; maxTeamAmount[iter->number] = maxTeamAmount[pathThrough] + teamAmount[iter->number];//更新团队数量 } else if (iter->value + minPath[pathThrough] == minPath[iter->number]) { minPathNumber[iter->number]++; if (maxTeamAmount[pathThrough] + teamAmount[iter->number] > maxTeamAmount[iter->number]) { maxTeamAmount[iter->number] = maxTeamAmount[pathThrough] + teamAmount[iter->number]; } } } } //更新完后寻找一个最小节点作为新的经过点 int min = maxValue + 10; int index; for (int j = 0; j < cityNum; j++) { if (isFind[j] == false && minPath[j] < min) { index = j; min = minPath[j]; } } pathThrough = index; isFind[index] = true; } pathNumber = minPathNumber[cityEnd]; teamNumber = maxTeamAmount[cityEnd]; } int main() { //输入 cin >> cityNum >> roadNum >> cityStart >> cityEnd; for (int i = 0; i < cityNum; i++) { cin >> teamAmount[i]; } for (int i = 0; i < roadNum; i++) { int c1, c2, length; cin >> c1 >> c2 >> length; graph[c1].push_back(Node(c2, length)); graph[c2].push_back(Node(c1, length)); } int pathNumber, teamNumber; stPath(pathNumber, teamNumber); cout << pathNumber << ' ' << teamNumber; return 0; }
a = list(map(int,input().split())) weight = list(map(int,input().split())) # 点权 G = [[1000000000] * a[0] for j in range(a[0])] # 邻接矩阵 for i in range(a[1]): c = list(map(int,input().split())) G[c[0]][c[1]],G[c[1]][c[0]] = c[2],c[2] d = [1000000000] * a[0] # 最短距离 num = [0] * a[0] # 最短路径条数 w = [0] * a[0] # 最大点权和 vis = [1] * a[0] # 是否访问过 d[a[2]] = 0 w[a[2]] = weight[a[2]] num[a[2]] = 1 while True: u,MIN = -1,1000000000 for j in range(a[0]): if vis[j] and d[j] < MIN: u,MIN = j,d[j] if u == -1: # 全访问完或不可达 break vis[u] = 0 for v in range(a[0]): if(vis[v] and G[u][v] != 1000000000): # 未曾访问且可达 if d[u] + G[u][v] < d[v]: # 如果距离更短 d[v] = d[u] + G[u][v] w[v] = w[u] + weight[v] num[v] = num[u] elif d[u] + G[u][v] == d[v]: # 如果权值更大 if w[u] + weight[v] > w[v]: w[v] = w[u] + weight[v] num[v] += num[u] print(num[a[3]],w[a[3]])核心就是Dijkstra算法了,用对了就很快。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * Dijkstra求source 到各顶点的最短距离/条数/累计人数最多(点权) */ public class Main { // 顶点数 private static int num; // 图 private static int[][] g; // 顶点是否已访问 private static boolean[] v; // 顶点s到各顶点的最短路径长度 private static int[] d; // 顶点s到各顶点的最短路的条数 private static int[] count; // 各顶点人数 private static int[] p; // 顶点s到各顶点的路径累计人数 private static int[] sum; // 顶点s到各顶点的最短路径初始值(极大值) private static int INF = 1_000_000_000; public static void main(String[] args) throws IOException { BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); String line1 = bf.readLine(); String[] lineas1 = line1.split(" "); num = Integer.valueOf(lineas1[0]); int roads = Integer.valueOf(lineas1[1]); int source = Integer.valueOf(lineas1[2]); int destination = Integer.valueOf(lineas1[3]); String line2 = bf.readLine(); String[] lineas2 = line2.split(" "); p = new int[num]; // 初始化各顶点人数 for (int i = 0; i < num; i++) { p[i] = Integer.valueOf(lineas2[i]); } // 初始化顶点s到各顶点的路径累计人数 sum = new int[num]; sum[source] = p[source]; // 初始化图 g = new int[num][num]; while (roads-- > 0) { String line = bf.readLine(); String[] lineas = line.split(" "); int i = Integer.valueOf(lineas[0]); int j = Integer.valueOf(lineas[1]); int length = Integer.valueOf(lineas[2]); g[i][j] = length; g[j][i] = length; } bf.close(); // 初始化顶点source到各顶点的路径 d = new int[num]; count = new int[num]; for (int i = 0; i < num; i++) { if (i == source) { d[i] = 0; count[i] = 1; } else { d[i] = INF; } } v = new boolean[num]; // Dijsktra int nums = num; while (nums-- > 0) { int u = minAndNotVisited(d, v); if (u == -1){ break; } v[u] = true; // 更新从source出发经u到u相连的顶点v的距离/最短路径条数/累计人数 for (int j = 0; j < num; j++) { if (g[u][j] > 0 && !v[j]) { if(d[u] + g[u][j] < d[j]) { d[j] = d[u] + g[u][j]; count[j] = count[u]; sum[j] = sum[u] + p[j]; } else if (d[u] + g[u][j] == d[j]) { count[j] = count[u] + count[j]; if((sum[u] + p[j])>sum[j]) { sum[j] = sum[u] + p[j]; } } } } } System.out.print(count[destination]+" "+sum[destination]); } /** * 获取未访问过且离source最近的顶点u,返回-1说明找不到和source相连接的且未访问过的顶点 */ private static int minAndNotVisited(int[] d, boolean[] v) { int u = -1; int min = INF; for (int i = 0; i < num; i++) { if (d[i] < min && !v[i]) { u = i; min = d[i]; } } return u; } }
//过了pat和牛客所有用例 #include <iostream> using namespace std; const int maxn=501,INF=1000000000; int n,g[maxn][maxn],d[maxn],weight[maxn],w[maxn],num[maxn]; bool visited[maxn]={false}; void dijkstra(int s) { int min,u; fill(d,d+maxn,INF); fill(w,w+maxn,0); fill(num,num+maxn,0); d[s]=0; w[s]=weight[s]; num[s]=1; for(int i=0;i<n;i++) { min=INF; for(int j=0;j<n;j++) { if(visited[j]==false&&d[j]<min) { u=j; min=d[j]; } } visited[u]=true; for(int v=0;v<n;v++) { if(visited[v]==false&&g[u][v]!=INF) { if(d[u]+g[u][v]<d[v]) { d[v]=d[u]+g[u][v]; w[v]=w[u]+weight[v]; num[v]=num[u]; } else if(d[u]+g[u][v]==d[v])//只在路径长度相等的情况下,选择点权最大的 { num[v]+=num[u]; if(w[v]<w[u]+weight[v]) w[v]=w[u]+weight[v]; } } } } } int main() { int edge,u,v,start,end; cin>>n>>edge>>start>>end; fill(g[0],g[0]+maxn*maxn,INF); for(int i=0;i<n;i++) cin>>weight[i]; for(int i=0;i<edge;i++) { cin>>u>>v; cin>>g[u][v]; g[v][u]=g[u][v]; } dijkstra(start); cout<<num[end]<<" "<<w[end]<<endl;; }
#include<stdio.h> #include<vector> using namespace std; struct way{ int next; int w; }; vector<way> E[504]; int han[504]; bool mark[504]; int Dis[504]; int Han[504]; //在dijkstra基础上加Han数组记录到达对应城市能得到的最大帮手 int main() { int n,m,c1,c2; while( scanf("%d%d%d%d",&n,&m,&c1,&c2)!= EOF ) { for( int i = 0 ; i < n ; i++ ) { E[i].clear(); Dis[i] = Han[i] = -1; mark[i] = false; } for( int i = 0 ; i < n ; i++ ) scanf("%d",&han[i]); //存储双向边 for( int i = 0 ; i < m ; i++ ) { int x,y,c; scanf("%d%d%d",&x,&y,&c); struct way s; s.next = y; s.w = c; E[x].push_back(s); s.next = x; E[y].push_back(s); } //count记录有几条最短路 int count; int tmp = c1; Dis[c1] = 0; Han[c1] = han[c1]; mark[c1] = true; for( int i = 1; i < n ; i++ ) { for( int j = 0 ; j < E[tmp].size() ; j++ ) { int nn = E[tmp][j].next; int cc = E[tmp][j].w; if( mark[nn] == true ) continue; if( Dis[nn] == -1 || Dis[nn] > Dis[tmp] + cc ) { Dis[nn] = Dis[tmp] + cc; Han[nn] = Han[tmp] + han[nn]; //若位到达目标城市的最短路,则记录 if( nn == c2 ) count = 1; } else if( Dis[nn] == Dis[tmp] + cc ) { //又存在一条到达目标城市且等于当前最短路的路径 if( nn == c2 ) count++; //比较帮手数目 if( Han[nn] < Han[tmp] + han[nn] ) Han[nn] = Han[tmp] + han[nn]; } } int min = 123123123; for( int j = 0 ; j < n ; j++ ) { if( mark[j] == true ) continue; if( Dis[j] == -1 ) continue; if( Dis[j] < min ) { min = Dis[j]; tmp = j; } } mark[tmp] = true; } printf("%d %d\n",count,Han[c2]); } return 0; }
#include<iostream>
#include<vector>
using namespace std;
struct Edge
{
int nextIndex,cost;
Edge(int a,int b)
{
this->nextIndex = a;
this->cost = b;
}
};
void find(int index,vector<Edge> *vertex,int findIndex,int cost,int rescueTeams,int *teams);
int already[100] ={false};
int minCost = 10000;
int maxResTeams = 0;
int differRoads = 0;
int main()
{
int N,M,c1,c2;
scanf("%d %d %d %d",&N,&M,&c1,&c2);
int *teams = new int[N];
vector<Edge> *vertex = new vector<Edge>[N];
for(int i=0;i<N;i++)
{
scanf("%d",teams+i);
//cout<<*(teams+i)<<endl;
}
//cout<<*(teams+1)<<endl;
for(int i =0;i<M;i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
vertex[a].push_back(Edge(b,c));
vertex[b].push_back(Edge(a,c));
//cout<<a<<"-"<<b<<"-"<<c<<endl;
}
////遍历看看是否正确
//for(int i=0;i<N;i++)
//{
// for(int j=0;j<vertex[i].size();j++)
// {
// cout<<"node:"<<i<<"--"<<vertex[i][j].cost<<"--"<<vertex[i][j].nextIndex<<endl;
// }
//}
//遍历找出两点之间的最短路径
already[c1]=true;
find(c1,vertex,c2,0,teams[c1],teams);
cout<<differRoads<<" "<<maxResTeams<<endl;
return 0;
}
void find(int index,vector<Edge> *vertex,int findIndex,int cost,int rescueTeams,int *teams)
{
for(unsigned int i=0;i<vertex[index].size();i++)
{
//找到了
int currentCost = cost+vertex[index][i].cost;
int currentRescuTeams = rescueTeams+teams[vertex[index][i].nextIndex];
//跳过已经访问过的
if(already[vertex[index][i].nextIndex])
continue;
if(vertex[index][i].nextIndex==findIndex)
{
//cout<<"cost-"<<currentCost<<"-"<<currentRescuTeams<<endl;
//已经找到了,就开始记录题目要求记录的
if(minCost>currentCost)
{
minCost = currentCost;
maxResTeams = currentRescuTeams;
differRoads = 1;
}
else if(minCost==currentCost)
{
if(maxResTeams<currentRescuTeams)
maxResTeams = currentRescuTeams;
differRoads++;
}
}else
{
//重要的地方,如何跳过已经找到的!
already[vertex[index][i].nextIndex]=true;
//未找到,继续找
find(vertex[index][i].nextIndex,vertex,findIndex,currentCost,currentRescuTeams,teams);
already[vertex[index][i].nextIndex]=false;
}
}
}
import java.util.*; import java.io.*; public class Main { private static int N, M, C1, C2; private static int[][] graph; private static int[] teams, dist, routes, rescues; private static boolean[] visited; private final static int INF = Integer.MAX_VALUE; public static void main(String[] args) throws IOException { // TODO Auto-generated method stub BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] line = br.readLine().split("\\s+"); N = Integer.parseInt(line[0]); M = Integer.parseInt(line[1]); C1 = Integer.parseInt(line[2]); C2 = Integer.parseInt(line[3]); graph = new int[N][N]; teams = new int[N]; dist = new int[N]; routes = new int[N]; rescues = new int[N]; visited = new boolean[N]; line = br.readLine().split("\\s+"); for (int i = 0; i < N; ++i) { teams[i] = Integer.parseInt(line[i]); } for (int[] row : graph) { Arrays.fill(row, INF); } for (int i = 0; i < M; ++i) { line = br.readLine().split("\\s+"); int v1 = Integer.parseInt(line[0]); int v2 = Integer.parseInt(line[1]); int w = Integer.parseInt(line[2]); graph[v1][v2] = w; graph[v2][v1] = w; } Arrays.fill(dist, INF); dist[C1] = 0; routes[C1] = 1; rescues[C1] = teams[C1]; for (int i = 0; i < N; ++i) { int u = -1, minDist = INF; for (int j = 0; j < N; ++j) { if (!visited[j] && dist[j] < minDist) { u = j; minDist = dist[j]; } } if (u == -1) { break; } visited[u] = true; for (int v = 0; v < N; ++v) { if (!visited[v] && graph[u][v] != INF) { if (dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; routes[v] = routes[u]; rescues[v] = rescues[u] + teams[v]; } else if (dist[u] + graph[u][v] == dist[v]) { routes[v] += routes[u]; if (rescues[u] + teams[v] > rescues[v]) { rescues[v] = rescues[u] + teams[v]; } } } } } System.out.format("%d %d\n", routes[C2], rescues[C2]); } }
#include<bits/stdc++.h> using namespace std; const int Max=510; const int INF=INT_MAX; int weight[Max],dis[Max],num[Max],w[Max]; int n,m,s,t; bool visit[Max]; struct node { int to; int l; node(int a,int b):to(a),l(b) {} }; vector<node> G[Max]; void Dijistra() { fill(dis,dis+Max,INF); memset(num,0,sizeof(num)); memset(w,0,sizeof(w)); dis[s]=0; num[s]=1; w[s]=weight[s]; for(int i=0; i<n; i++) { int u=-1,Min=INF; for(int j=0; j<n; j++) { if(!visit[j]&&dis[j]<Min) { Min=dis[j]; u=j; } } if(u==-1) return ; visit[u]=1; for(int k=0; k<G[u].size(); k++) { int v=G[u][k].to; if(!visit[v]) { if(dis[u]+G[u][k].l<dis[v]) { dis[v]=dis[u]+G[u][k].l; w[v]=w[u]+weight[v]; num[v]=num[u]; } else if(dis[u]+G[u][k].l==dis[v]) { if(weight[v]+w[u]>w[v]) { w[v]=weight[v]+w[u]; } num[v]+=num[u]; } } } } } int main() { scanf("%d %d %d %d",&n,&m,&s,&t); for(int i=0; i<n; i++) { scanf("%d",&weight[i]); } int from,to,L; for(int i=0; i<m; i++) { scanf("%d %d %d",&from,&to,&L); G[from].emplace_back(node(to,L)); G[to].emplace_back(node(from,L)); } Dijistra(); printf("%d %d\n",num[t],w[t]); return 0; }
#include <iostream> #include <cstdio> #include <algorithm> #define INF 100000000 using namespace std; int n,m,c1,c2; int num[500]; int tu[500][500]; bool visited[500]; int num_of_luxian[500]; int maxgather[500]; int dis[500]; void dijs(){ dis[c1] = 0; num_of_luxian[c1] = 1; maxgather[c1] = num[c1]; for(int i = 0;i<n;i++){ int mina = INF,u = -1; for(int j = 0;j<n;j++){ if(visited[j]==false&&dis[j]<mina){ mina = dis[j]; u = j; } } if(u==-1){ return; } visited[u] = true; if(u==c2){ return; } for(int j = 0;j<n;j++){ if(visited[j]==false&&tu[u][j]<INF){ if(tu[u][j]+dis[u]<dis[j]){ dis[j] = tu[u][j]+dis[u]; num_of_luxian[j] = num_of_luxian[u]; maxgather[j] = num[j]+maxgather[u]; }else if(tu[u][j]+dis[u]==dis[j]){ num_of_luxian[j]+=num_of_luxian[u]; maxgather[j] = max(maxgather[j],maxgather[u]+num[j]); } } } } } int main(){ fill(visited,visited+500,false); fill(dis,dis+500,INF); fill(tu[0],tu[0]+500*500,INF); fill(num_of_luxian,num_of_luxian+500,0); fill(maxgather,maxgather+500,0); cin>>n>>m>>c1>>c2; for(int i = 0;i<n;i++){ cin>>num[i]; } for(int i = 0;i<m;i++){ int a,b,c; cin>>a>>b>>c; tu[a][b] = c; tu[b][a] = c; } dijs(); cout<<num_of_luxian[c2]<<" "<<maxgather[c2]<<endl; return 0; }
#include <cstdio> (802)#include <vector> #include <set> (855)#include <climits> #include <algorithm> using namespace std; const int maxv = 500; const int INF = INT_MAX; struct edge{ int e_end, e_weight; edge(int a, int b): e_end(a), e_weight(b) {} }; int N, M, S, D; int v_weight[maxv], d[maxv]; int path_count[maxv]={}; int team[maxv]={}; vector<edge> graph[maxv]; set<int> pre[maxv]; void init(); void bellmanFord(); int main(){ scanf("%d%d%d%d", &N, &M, &S, &D); for(int i=0; i<N; i++) scanf("%d", &v_weight[i]); while(M--){ int c1, c2, l; scanf("%d%d%d", &c1, &c2, &l); graph[c1].push_back(edge(c2, l)); graph[c2].push_back(edge(c1, l)); } init(); bellmanFord(); printf("%d %d", path_count[D], team[D]); return 0; } void init(){ fill(d, d+N, INF); d[S] = 0; path_count[S] = 1; team[S] = v_weight[S]; return; } void bellmanFord(){ for(int k=0; k<N-1; k++){ //最多N-1次循环 for(int i=0; i<N; i++){ //每个顶点i if(d[i]==INF) continue; //重要 int e = graph[i].size(); for(int j=0; j<e; j++){ //每条边i -> v int v = graph[i][j].e_end; int w = graph[i][j].e_weight; if(d[i]+w<d[v]){ //第一标准更优。找到更短路径 d[v] = d[i] + w; team[v] = team[i] + v_weight[v]; path_count[v] = path_count[i]; pre[v].clear(); pre[v].insert(i); } else if(d[i]+w==d[v]){ //第一标准失效。找到长度相同的另一条路 //重新统计路径条数 pre[v].insert(i); path_count[v] = 0; for(set<int>::iterator it=pre[v].begin(); it!=pre[v].end(); it++){ path_count[v] += path_count[*it]; } //第二标准更优 if(team[i]+v_weight[v]>team[v]){ team[v] = team[i] + v_weight[v]; } } } } } return; }
//MemoryC 20190508 import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main { private static int[]rescueNumbers; public static void main(String[] args) { Scanner scanner=new Scanner(System.in); int N=scanner.nextInt(); int M=scanner.nextInt(); int C1=scanner.nextInt(); int C2=scanner.nextInt(); rescueNumbers=new int[N]; List<Integer> cities=new ArrayList<>(); for(int i=0;i<N;i++){ rescueNumbers[i]=scanner.nextInt(); cities.add(i); } for(int i=0;i<M;i++){ Road.addRoad(scanner.nextInt(), scanner.nextInt(), scanner.nextInt()); } List<Route> routes=findRoutes(cities,C1,C2); System.out.println(routes.size()+" "+routes.get(0).rescueNumber); } private static List<Route>findRoutes(List<Integer> cities, int from, int to){ List<Route> routes=new ArrayList<>(); if(from==to){ Route route=new Route(0,rescueNumbers[from]); // route.rt="—>"+from; routes.add(route); return routes; } List<Road>roads=Road.getRoadsByCity(cities,from); int minLength=Integer.MAX_VALUE; int maxRescue=0; List<Integer> subCities = new ArrayList<>(cities); subCities.remove(Integer.valueOf(from)); for(Road road:roads){ int otherCity=road.city1^road.city2^from; List<Route>subRoutes=findRoutes(subCities,otherCity,to); if(subRoutes.isEmpty()){ continue; } for(Route subRoute:subRoutes){ subRoute.length+=road.length; if(subRoute.length<minLength){ minLength=subRoute.length; routes.clear(); } if(subRoute.length==minLength){ subRoute.rescueNumber+=rescueNumbers[from]; // subRoute.rt="—>"+from+subRoute.rt; if(subRoute.rescueNumber>maxRescue){ maxRescue=subRoute.rescueNumber; routes.add(0,subRoute); }else { routes.add(subRoute); } } } } return routes; } static class Road{ int city1; int city2; int length; private static List<Road>roads=new ArrayList<>(); static List<Road> getRoadsByCity(List<Integer>cities,int city){ List<Road> roadList=new ArrayList<>(); for(Road road:roads){ if((cities.contains(road.city1)&&cities.contains(road.city2))&&(road.city1==city||road.city2==city)){ roadList.add(road); } } return roadList; } static void addRoad(int city1, int city2, int length) { Road road=new Road(); road.city1 = city1; road.city2 = city2; road.length = length; roads.add(road); } } static class Route{ int length; int rescueNumber; // String rt; Route(int length, int rescueNumber) { this.length = length; this.rescueNumber = rescueNumber; } } }
//MemoryC 20190508 import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main_Dijkstra { private static int[]rescueNumbers; static Road[][] roads; public static void main(String[] args) { Scanner scanner=new Scanner(System.in); int N=scanner.nextInt(); int M=scanner.nextInt(); int C1=scanner.nextInt(); int C2=scanner.nextInt(); rescueNumbers=new int[N]; roads=new Road[N][N]; for(int i=0;i<N;i++){ rescueNumbers[i]=scanner.nextInt(); } List<Road> sureList=new ArrayList<>(); List<Road> unSureList=new ArrayList<>(); for(int i=0;i<M;i++){ int c1=scanner.nextInt(); int c2=scanner.nextInt(); Road road=new Road(c1,c2,scanner.nextInt()); roads[c1][c2]=road; roads[c2][c1]=road; if(c1==C1||c2==C1){ unSureList.add(road); } } while (!unSureList.isEmpty()){ int minLength=0x7fffffff; List<Road> minRoads=new ArrayList<>(); for(Road r:unSureList){ if(r.length<minLength){ minRoads.clear(); minRoads.add(r); minLength=r.length; }else if(r.length==minLength){ minRoads.add(r); } } sureList.addAll(minRoads); unSureList.removeAll(minRoads); //更新U if(unSureList.isEmpty()||minRoads.contains(roads[C1][C2])){ break; }else{ for(Road ur:unSureList){ int tar=ur.city1^ur.city2^C1; for(Road sr:minRoads){ int mid=sr.city1^sr.city2^C1; if(mid==tar||roads[tar][mid]==null){ continue; } int twoLen=sr.length+roads[tar][mid].length; if(twoLen<ur.length){ ur.length=twoLen; ur.rescueNumber=sr.rescueNumber+roads[tar][mid].rescueNumber-rescueNumbers[mid]; ur.routeCount=1; }else if(twoLen==ur.length){ ur.rescueNumber=Integer.max( ur.rescueNumber,sr.rescueNumber+roads[tar][mid].rescueNumber-rescueNumbers[mid]); ur.routeCount++; } } } } } System.out.println(roads[C1][C2].routeCount+" "+roads[C1][C2].rescueNumber); } static class Road{ int city1; int city2; int length; int routeCount=1; int rescueNumber; Road(int city1, int city2, int length) { this.city1 = city1; this.city2 = city2; this.length = length; rescueNumber=rescueNumbers[city1]+rescueNumbers[city2]; } } }