hdu6026 dijkstra

题目链接:http://icpc.njust.edu.cn/Problem/Hdu/6026/

题意大致是:给定一个图,要求删边使他变成树,使得每个点到0的距离就是原图中0到这个点的最短路径。其实就是最短路树。

证明1: 对于每个结点我们只要知道有多少条路径到它的距离是最短路长度,记为cnt,那么就有cnt条边连着前驱结点,首先,能保证的是每个点都是0能够到达的,所以前驱结点一定是全部都能到达的,就是他们的d一定存在,所以我们只要删除cnt-1条边,留下一条就能建成最短路树。对于每个结点,我们扫描之后按照乘法规则将方案数相乘即可。

下面分三种情况来证明这是一棵树

①、假设有一个结点p连着一个结点q,有dis[q]<dis[p]+edge[p][q],那么这就构成了一个圈,我们删除edge[p][q]就变成了无圈而且从0都能到达这两个结点,对于其他边,我们也可以这样删除。

②、假设有一个结点p连着一个结点q,有dis[q]=dis[p]+edge[p][q],我们从证明1中知道这样的p只会有一个,因为这样的边我们的算法中已经删的只剩下一条。所以这种情况不构成圈。

③、假设有一个结点p连着一个结点q,有dis[q]>dis[p]+edge[p][q],与dis[q]是q的最短路长度矛盾。

综上:算法完成之后的图成为了树。

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef unsigned int ui;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 #define pf printf
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define prime1 1e9+7
 9 #define prime2 1e9+9
10 #define pi 3.14159265
11 #define lson l,mid,rt<<1
12 #define rson mid+1,r,rt<<1|1
13 #define scand(x) scanf("%llf",&x) 
14 #define f(i,a,b) for(int i=a;i<=b;i++)
15 #define scan(a) scanf("%d",&a)
16 #define mp(a,b) make_pair((a),(b))
17 #define P pair<int,int>
18 #define dbg(args) cout<<#args<<":"<<args<<endl;
19 #define inf 0x3f3f3f3f
20 const int maxn=100;
21 const int mod=1e9+7;
22 int n,m,t;
23 int d[maxn],edge[maxn][maxn];
24 void dijkstra(int src)
25 {
26     priority_queue<P,vector<P> ,greater<P> >q;
27     f(i,0,n-1)d[i]=inf;
28     d[src]=0;
29     q.push(mp(0,src));
30     while(!q.empty())
31     {
32         P now=q.top();
33         q.pop();
34         int u=now.second;
35         if(d[u]<now.first)continue;
36         f(i,0,n-1)
37         {
38             if(edge[u][i]&&d[i]>d[u]+edge[u][i])
39             {
40                 d[i]=d[u]+edge[u][i];
41                 q.push(mp(d[i],i));
42             }
43         }
44     }
45 }
46 int main()
47 {
48     //freopen("input.txt","r",stdin);
49     //freopen("output.txt","w",stdout);
50     std::ios::sync_with_stdio(false);
51     while(scan(n)!=EOF)
52     {
53         char c;
54         f(i,0,n-1)
55             f(j,0,n-1)
56             {
57                 scanf(" %c",&c);
58                 edge[i][j]=c-'0';
59             }
60             ll ans=1;
61             dijkstra(0);
62             f(i,1,n-1)
63             {
64                 int cnt=0;
65                 f(j,0,n-1)
66                 {
67                     if(edge[i][j]&&(d[j]+edge[j][i]==d[i]))cnt++;
68                 }
69                 ans=(ans*cnt)%mod;
70             }
71             pf("%lld\n",ans);
72     }
73     
74  } 

 

猜你喜欢

转载自www.cnblogs.com/randy-lo/p/12551836.html