NOIP2017 7.17模拟 Minimum (最短路+最小生成树)
来源:互联网 发布:凸的网络意思是什么 编辑:程序博客网 时间:2024/06/16 07:24
题目描述:
给出一幅由 n 个点 m 条边构成的无向带权图。
其中有些点是黑点,另外点是白点。
现在每个白点都要与他距离最近的黑点通过最短路连接(如果有很多个,连所有的),我们想要使得花费的代价最小。请问这个最小代价是多少?
注意:最后选出的边保证每个白点到黑点的距离任然是最短距离。(这句话题解代码也无法实现,就不管了)
输入:
第一行两个整数 n,m ;
第二行 n 个整数,0 表示白点,1 表示黑点;
接下来 m 行,每行三个整数 x,y,z ,表示一条连接 x 和 y 点,权值为 z 的边。
输出:
如果无解,输出“impossible”,否则,输出最小代价。
样例数据:
输入
5 7
0 1 0 1 0
1 2 11
1 3 1
1 5 17
2 3 1
3 5 18
4 5 3
2 4 5
输出
5
【数据范围】
对 30% 的输入数据 :1≤n≤10,1≤m≤20;
对 100% 的输入数据 :1≤n≤100000,1≤m≤200000,1≤z≤1000000000 。
题意:将所有白点和黑点通过在最短路上的路径连接,求最小代价,无解的情况是存在白点与黑点无法连通。通过分析我们可以发现,有解的情况可以分为两个问题考虑:
1、求最短路;
2.并找到在最短路上的边;
3、通过这些边跑一边最小生成树,统计边权之和。
对于第一个问题,因为是要求任意一个白点到任意一个黑点的距离,我们可以想到建一个超级点,由它向每一个黑点连一条边权为0的有向边,然后由这个超级点跑一次最短路(迪杰斯特拉或spfa),就行了;
对于第二个问题,由最短路的更新方法
if(dis[a]+val[i]<dis[to[i]]) dis[to[i]]=dis[a]+val[i];
我们可以想到,遍历每条边,满足dis[edge[i].start]==dis[edge[i].end+edge[i[.val那么这条边一定是最短路上的边,由此我们可以找到所有最短路上的边
对于第三个问题,裸的最小生成树,在此就不赘述了;
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<ctime>#include<cstring>#include<string>#include<iomanip>#include<iostream>#include<cctype>#include<queue>using namespace std;int n,m,tot,sup,cnt,len,fa[100005],next[500010],first[100005],to[500010];long long dis[100005];long long val[500010];bool black[100005],ok=true;//---------------------priority_queue< pair<int,int> > que;pair<int,int> temp;//---------------------struct node{ int st,end; long long val;}a[400010];bool cmp(const node&a,const node&b){ return a.val<b.val;}//---------------------inline long long Readint(){ long long i=0,f=1; char ch; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=-1; for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0'; return i*f;}//---------------------inline void add(int x,int y,long long z){ next[++tot]=first[x]; first[x]=tot; to[tot]=y; val[tot]=z;}//---------------------inline void djstra(int root){ dis[root]=0; temp.first=0; temp.second=root; que.push(temp); while(!que.empty()){ temp=que.top(); que.pop(); int a=temp.second; for(int i=first[a];i;i=next[i]){ if(dis[a]+val[i]<dis[to[i]]){ dis[to[i]]=dis[a]+val[i]; pair<int,int> s; s.first=-dis[to[i]]; s.second=to[i]; que.push(s); } } }}//---------------------inline int find(int x){ if(x==fa[x]) return x; fa[x]=find(fa[x]); return fa[x];}//---------------------int main(){ freopen("minimum.in","r",stdin); n=Readint(),m=Readint(); memset(first,0,sizeof(first)); for(int i=0;i<=n;i++) fa[i]=i; for(int i=0;i<=n;i++) dis[i]=1e16+7; for(int i=1;i<=n;i++){ black[i]=Readint(); if(black[i]) add(sup,i,0); } for(int i=1;i<=m;i++){ int x,y; long long z; x=Readint(),y=Readint(),z=Readint(); add(x,y,z),add(y,x,z); } djstra(sup); for(int i=1;i<=n;i++) if(dis[i]==1e16+7) ok=false; if(!ok){ cout<<"impossible"<<endl; return 0; } for(int i=1;i<=n;i++){ for(int p=first[i];p;p=next[p]){ if(dis[to[p]]==val[p]+dis[i]){ a[++len].st=i,a[len].end=to[p],a[len].val=val[p]; } } } long long ans=0; sort(a+1,a+1+len,cmp); for(int i=1;i<=len;i++){ int fx=find(a[i].st),fy=find(a[i].end); if(fx!=fy){ fa[fx]=fy; ans+=a[i].val; cnt++; } if(cnt==n-1) break; } cout<<ans<<endl; return 0;}
- NOIP2017 7.17模拟 Minimum (最短路+最小生成树)
- 最短路(最小生成树)
- C++——Minimum——最短路、最小生成树
- 【JZOJ5287】【NOIP2017提高组模拟】最短路
- 【区别】最短路&最小生成树
- BOJ 333 最小生成树+最短路
- 区别 最短路跟最小生成树
- 图论 最小生成树 和最短路
- 最小生成树&最短路模板
- 【模板】最短路&&最小生成树
- 最短路与最小生成树
- uva 10816 最小生成树 + 最短路
- NOIP2017模拟 玩游戏 最小生成树 树上倍增
- 【NOIP2017提高A组模拟8.16】最短路
- 【JZOJ5287】【NOIP2017提高A组模拟8.16】最短路
- 并查集&最小生成树、最短路
- 图论--最小生成树和最短路1
- 最小生成树与最短路的区别
- Java中的类
- tomcat应用启动异常:Exception loading sessions from persistent storage
- HDU 4857 逃生(逆向拓扑求最小靠前)
- django 实践后的问题总结
- 艾默生plc编程软件(ControlStar)下载 v2.40中文免费版
- NOIP2017 7.17模拟 Minimum (最短路+最小生成树)
- - Cleaning Shifts
- 《Java设计模式之工厂模式》
- STM32半主机模式
- SpringBoot中集成kaptcha验证码
- 使用paramiko的SFTP get或put整个目录(转)
- Java Web 文章管理系统(Jsp+Ajax+JDBC+MySql实现)
- 堆应用 Fence Repair
- 字体管理工具(FontExpert 2016) v14.0 免费版