题目:
http://icpc.njust.edu.cn/Problem/Hdu/3268/
代码:
//#include<bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <ctype.h> //toloewr()
#include <set>
#include <map>
#include <iomanip>// cout<<setprecision(1)<<fixed<<a;
#include <vector>
#include <time.h>
#include <assert.h> //assert
#include <cmath>
#include <algorithm>
#include <bitset>
#include <stack>
#include <queue>
using namespace std;
const int maxn=50;
const int inf=0x7f7f7f7f;
typedef pair<int,int> p;//<a,b> 起点到b的最短距离为a
struct edge {
int to;
int cost;
edge(int tto=0,int ccost=0):to(tto),cost(ccost){}
};
int t,n,m;
int d[maxn];
//int prev[maxn];
vector<edge> g[maxn];
int val[maxn],f[maxn];
void dijkstra(int s) {
priority_queue<p,vector<p>,greater<p> >qu;//堆按照p的first(最短距离)排序,小顶堆
fill(d,d+n+1,inf);
// fill(prev,prev+n+1,-1);//+n 太小了...
// memset(prev,sizeof(prev),-1);//混用会报错
d[s]=0;
qu.push(p(0,s));//从起点出发到顶点s的最短距离为0
while(!qu.empty()) {
p temp=qu.top();
qu.pop();
int tmpv=temp.second;
if(temp.first>d[tmpv]) continue;//跳过更新过程中入队的非最小值
for(int i=0;i<g[tmpv].size();++i) {//遍历该顶点连出的每条边
edge e=g[tmpv][i];
if(d[e.to]>d[tmpv]+e.cost) {
d[e.to]=d[tmpv]+(int)e.cost;
// prev[e.to]=tmpv;
qu.push(p(d[e.to],e.to));
}
}
}
}
//vector<int> getpath(int t) {//s -> t
// vector<int> path;
// while(t!=-1) {//从 t 倒着走,一直走到 s
// path.push_back(t);
// t=prev[t];
// }
// reverse(path.begin(),path.end());
// return path;
//}
int main() {
int a,b,c;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<=n;++i) g[i].clear();
memset(val,0,sizeof(val));
for(int i=0;i<n;++i){
scanf("%d%d",&a,&b);
val[a]=b;
g[0].push_back(edge(a,b-1));
// g[a].push_back(edge(0,b-1));
}
scanf("%d",&m);
for(int i=0;i<m;++i){
scanf("%d%d%d",&a,&b,&c);
g[a].push_back(edge(b,c));
// g[b].push_back(edge(a,c));
}
for(int i=1;i<=maxn;++i){
for(int j=1;j<=maxn;++j){
if(val[i]!=0 && i!=j &&val[i]==val[j]) {
g[i].push_back(edge(j,0));
g[j].push_back(edge(i,0));
}
}
}
dijkstra(0);
for(int i=1;i<maxn;++i){
if(val[i]){
printf("%d %d\n",i,d[i]);
}
}
int num=0;
memset(f,0,sizeof(f));///读题要注意 究竟要统计什么
for(int i=1;i<maxn;++i){///i j k内外层本题没差别
if(val[i]!=0){///思路要清晰 是用val判是否在读入中出现 整个统计过程和d[i]是不是为零没有关系
for(int j=1;j<maxn;++j){
if(val[j]!=0)
for(int k=1;k<maxn;++k){
if(val[k]!=0){
if(f[k]==0 && d[i]+d[j]==d[k] && i!=j && i!=k && j!=k) num++,f[k]=1;
}
}
}
}
}
printf("%d\n",num);
}
return 0;
}