洛谷 AT2434 JOI 公園 (JOI Park) 题解

人生第一次AC黑题,我太感动了。

每日一题 day31 打卡

Analysis

先跑遍DJ,求出1到 i的最短路。
得到每个点到 1号点的距离后,从小到大排序一遍,这时便可以枚举每个点到 1号点的距离修筑地下隧道,每次将每个被枚举到的点加入一个集合(实际上可以由边权总和-与该点相连所有没有计入集合的边权总和)。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #define int long long
 7 #define maxn 200000+10
 8 #define INF 2147483647
 9 using namespace std;
10 inline int read() 
11 {
12     int x=0;
13     bool f=1;
14     char c=getchar();
15     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
16     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
17     if(f) return x;
18     return 0-x;
19 }
20 inline void write(long long x)
21 {
22     if(x<0){putchar('-');x=-x;}
23     if(x>9)write(x/10);
24     putchar(x%10+'0');
25 }
26 int n,m,c,max_d=-INF,ans,sum,cnt;
27 int head[2*maxn],book[maxn],vis[maxn];
28 struct node
29 {
30     int u,v,w,nex;
31 }edge[2*maxn];
32 struct node1
33 {
34     int dis,num;
35 }x[maxn];
36 inline bool cmp(node1 x,node1 y)
37 {
38     return x.dis<y.dis;
39 }
40 inline void add(int x,int y,int z)
41 {
42     edge[++cnt].u=x;
43     edge[cnt].v=y;
44     edge[cnt].w=z;
45     edge[cnt].nex=head[x];
46     head[x]=cnt;
47 }
48 inline void dijkstra()
49 {
50     priority_queue<pair<int,int> > q;
51     for(int i=1;i<=n;i++) x[i].dis=INF;
52     memset(book,0,sizeof(book));
53     x[1].dis=0;
54     q.push(make_pair(0,1));
55     while(!q.empty())
56     {
57         int from=q.top().second;
58         q.pop();
59         if(book[from]) continue;
60         book[from]=1;
61         for(int i=head[from];i;i=edge[i].nex)
62         {
63             int to=edge[i].v,val=edge[i].w;
64             if(x[to].dis>x[from].dis+val)
65             {
66                 x[to].dis=x[from].dis+val;
67                 q.push(make_pair(-x[to].dis,to));
68             }
69         }
70     }    
71 }
72 signed main()
73 {
74     n=read();m=read();c=read();
75     for(int i=1;i<=m;i++)
76     {
77         int x=read(),y=read(),z=read();
78         add(x,y,z);
79         add(y,x,z);
80         sum+=z;
81     }
82     dijkstra();
83     for(int i=1;i<=n;i++) x[i].num=i;
84     sort(x+1,x+n+1,cmp);
85     vis[1]=1;
86     int ans=sum;
87     for(int i=1;i<=n;i++)
88     {
89         vis[x[i].num]=1;
90         for(int j=head[x[i].num];j;j=edge[j].nex)
91             if(vis[edge[j].v])
92                 sum-=edge[j].w;
93         ans=min(ans,sum+x[i].dis*c);
94     }
95     write(ans);
96     return 0;
97 }

请各位大佬斧正(反正我不认识斧正是什么意思)

原文地址:https://www.cnblogs.com/handsome-zyc/p/11767086.html