公路通行税(Ceoi99)
版权声明:本篇随笔版权归作者YJSheep(www.cnblogs.com/yangyaojia)所有,转载请保留原地址!
在PALMIA国家内,有N个城市由公路相连(每条公路恰好双向连接两个城市)。经由一条公路或多条公路,从任一城市出发可以到达其余各个城市。直到今年,公路上才要征收公路通行税。在每条公路的中间,有一征税员,从每一辆经由此路的车收取 1 PALMIA COIN(1PC)。
政府官员决定减少收税员而推行公路印花。如果一辆车欲进入一条公路,就必须将这张印花贴在窗上。
政府官员决定:一年的公路印花的价值相当于在两个最远城市之间进行100次旅行所需的费用。两个城市之间的距离是从一个城市到达第二个城市所需经过的最少数目的公路数。
你的任务是编写一个程序计算出公路印花的价值。
输入数据:
输入文件中包含几组数据。每组的第一行包括整数N和M(中间被一个空格隔开),N是该国家中城市的数目,M是公路的数目(1≦N≦1000,1≦M≦2000)。城市由整数进行编号,从1到N。接下来的M行,每行均包含一对整数A,B(1≦A,B≦N),中间由一空格隔开,代表在城市A与B之间有一条公路。在最后一组数后仅有一行,是两个0,中间被一空格隔开。
输出数据:
对输入文件中的各组数据,输出文件中包含一行,表示公路印花的价值。
输入输出示例:
TOLLS.IN:
4 4
1 2
2 3
4 2
3 4
0 0
TOLLS.OUT:
200
解题报告
简单来说就是寻找图的直径,因为数据n<=1000,对于每个点用最短路为O(n*nlogn)是过不了的,但注意到路径长度只有1,所以我们可以用BFS,时间勉勉强前过去。不过,我们可以先对某个点用单源最短路。然后记录距离其最远的点,再依次对他们用BFS,这样效率会快很多而且答案也是正确的。
#include<bits/stdc++.h> #define MAXN 1000+1 #define MAXM 500000+1 #define Pair pair<int,int> using namespace std; int n,m,t,v[MAXN],num; int head[MAXN],g[MAXN][MAXN]; queue<Pair> emp; struct Edge{int dis;int to,next; }edge[MAXM]; int read() {int in=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar());for(;ch>='0'&&ch<='9';ch=getchar()) in=in*10+ch-'0';return in; } void add(int from,int to,int dis) {edge[++num].next=head[from];edge[num].to=to;edge[num].dis=dis;head[from]=num; } void bfs(int s,int &maxl) {memset(v,0,sizeof(v));queue<Pair> h=emp;h.push(Pair(0,s));while(h.size()>0){int k=h.front().second,diss=h.front().first;h.pop();v[k]=1;for(int i=head[k];i;i=edge[i].next)if (v[edge[i].to]==0){v[edge[i].to]=1;g[edge[i].to][k]=g[k][edge[i].to]=diss+1;h.push(Pair(diss+1,edge[i].to));maxl=max(maxl,diss+1);}} } void dij(int s) {memset(v,0,sizeof(v));priority_queue<Pair,vector<Pair>,greater<Pair> > h;int dis[MAXN],maxx=0;for(int i=1;i<=n;i++) dis[i]=999999999;dis[s]=0;h.push(Pair(dis[s],s));while(h.size()>0){int k=h.top().second;h.pop();if(v[k]) continue;v[k]=1;for(int i=head[k];i;i=edge[i].next){if(dis[k]+edge[i].dis<dis[edge[i].to]){dis[edge[i].to]=dis[k]+edge[i].dis;h.push(Pair(dis[edge[i].to],edge[i].to));}}}queue<int> q;for(int i=1;i<=n;i++)if(dis[i]!=999999999) maxx=max(maxx,dis[i]);for(int i=1;i<=n;i++) if(dis[i]==maxx) q.push(i);if(maxx!=0)while(q.size()>0){bfs(q.front(),maxx);q.pop();}else{for(int i=1;i<=n;i++){bfs(i,maxx);}}printf("%d\n",maxx*100); } int main() {while(scanf("%d%d",&n,&m)==2){int maxl=0;if(m==0&&n==0) return 0;memset(edge,0,sizeof(edge));memset(g,0,sizeof(g));num=0;//memset(dis,0,sizeof(dis));memset(head,0,sizeof(head));for(int i=1;i<=m;i++){int a,b;a=read();b=read();add(a,b,1);add(b,a,1);}dij(1);}return 0; }