懶得貼上試題了~發個連結:NOI2007 Day1試題連結
【分析】
這是這幾年NOI中最簡單的題了~就是一個多源最短路+乘法原理。
用Map[i][j]表示i、j之間的最短路徑長度;
用Path[i][j]表示i、j之間最短路徑的條數(初始化為1)。
先用Floyd算法求每兩點之間的最短路,鬆弛時要注意,如果出現:
Map[i][k]+Map[k][j]==Map[i][j] 則說明這又是最短路,所以Path[i][j]+=Path[i][k]*Path[k][j]。
如果可以鬆弛,即Map[i][k]+Map[k][j]<Map[i][j],則Path[i][j]=Path[i][k]*Path[k][j]即可。
最後亂搞一個三重循環求I(v),按照題意走即可AC。
【我的代碼】
裸代碼RawCode
- #include <cstdio>
- #include <cstdlib>
- #define inputfile freopen("network.in","r",stdin)
- #define outputfile freopen("network.out","w",stdout)
- #define MAXN 101
- #define MAX 1000000000
- #define LL long long
- using namespace std;
- int N,M;
- int Map[MAXN][MAXN];
- LL Path[MAXN][MAXN];
- void init()
- {
- fscanf(stdin,"%d %d\n",&N,&M);
- for(int i=1;i<=N;i++)
- {
- for(int j=1;j<=N;j++)
- Map[i][j]=MAX,Path[i][j]=1;
- Map[i][i]=0;
- }
- int a,b,v;
- for (int i=1;i<=M;i++)
- {
- fscanf(stdin,"%d %d %d\n",&a,&b,&v);
- Map[a][b]=v;
- Map[b][a]=v;
- }
- }
- void Floyd()
- {
- for (int k=1;k<=N;k++)
- {
- for (int i=1;i<=N;i++)
- {
- for (int j=1;j<=N;j++)
- {
- if(k==i || k==j || i==j)
- continue;
- if(Map[i][k]+Map[k][j]==Map[i][j])
- Path[i][j]+=Path[i][k]*Path[k][j];
- if(Map[i][k]+Map[k][j]<Map[i][j])
- Map[i][j]=Map[i][k]+Map[k][j],
- Path[i][j]=Path[i][k]*Path[k][j];
- }
- }
- }
- }
- void solve()
- {
- for (int v=1;v<=N;v++)
- {
- double Ans=0;
- for (int s=1;s<=N;s++)
- {
- for (int t=1;t<=N;t++)
- {
- if(s==v || t==v || s==t)
- continue;
- if(Map[s][v]+Map[v][t]!=Map[s][t])
- continue;
- double a=double(Path[s][v]*Path[v][t]);
- double b=double(Path[s][t]);
- double res=a/b;
- Ans+=res;
- }
- }
- fprintf(stdout,"%.3lf\n",Ans);
- }
- }
- int main()
- {
- inputfile,outputfile;
- init();
- Floyd();
- solve();
- return 0;
- }
沒有留言:
張貼留言