HDU - 5521 Meeting (Dijkstra)
思路:
看了好久才看懂题意,文中给了n个点,有m个集合,每个集合有s个点,集合内的每两个点之间有一个权值为t的边,现在有两个人,要从1号点,和n号点,走到同一个顶点,问最少花费以及花费最少的点。
那就直接跑两遍最短路,然后枚举每一点,取最短路最大值最小的点。
然而这么浅显的做法却MLE啦,真是用心险恶的出题人呀。
其实仔细想一想就知道了,题目的要求是,每个集合里面,都是一个完全图,如果只有一个集合,那么2e5个点,边的条数就是4e10条,爆内存简直是必然的。所以需要在建图的时候优化,或者是换一种算法。如果要在建图的时候优化,那么就要忽视那些,在集合内,却没有与其他集合相连的点。如何找出这些点呢?很容易想到,如果一个点在输入的数据中出现了两次或以上,那么它一定是与其他集合有关的,但是如何记录这些点是一个很大的问题。如果用数组记录下每个集合有哪些点,或者每个点属于哪些集合,很明显都是不行的,但是如果使用vector呢?既然题目中已经提到了,s的和不会超过1e6,那么这样或许是可行的。我首先尝试了一下,记录下每个集合有哪些点。
然而还是炸了内存。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
自闭。
回来再想一想,好像还是没有最开始的完全图问题,因为这数据可以有两个集合,而这两个集合都是满的。。。。。(好歹毒呀)
最后我还是无耻得看了一下其他人的题解.了解了一种可以大幅减少完全图的边数.方法就是,在每一个完全图的边上,建一个虚拟点,让每一点去虚拟点的距离就是t,回来是0.如果是一般情况,也就是说,点到点之间的距离不相等的话,这个方法貌似就无法使用啦.
代码:
#include<iostream> #include<algorithm> #include<vector> #include<queue> #include<deque> #include<stack> #include<map> #include<set> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #define fuck(x) cout<<#x<<" = "<<x<<endl; using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 200086; const int inf = 1.0e9+5; const ll INF = 999999999999999; const double eps = 1e-6; int n,m; ll diss1[maxn],diss2[maxn]; int num[maxn]; vector<int>u[maxn]; vector<ll>w[maxn]; bool book[2*maxn]; void init() { for(int i=1;i<=n*2;i++){ u[i].clear(); w[i].clear(); diss1[i]=diss2[i]=INF; } } struct node { int x; ll s; bool operator<(const node p)const{return p.s<s;} }; int Dijkstra(int sx,ll *dis) { memset(book,0,sizeof(book)); dis[sx]=0ll; priority_queue<node>q; node exa; exa.x=sx; exa.s=0ll; q.push(exa); while(!q.empty()){ exa=q.top();q.pop(); if(book[exa.x]){continue;} book[exa.x]=true; int t=exa.x; int siz=u[t].size(); for(int i=0;i<siz;i++){ if(dis[u[t][i]]>dis[t]+w[t][i]){ dis[u[t][i]]=dis[t]+w[t][i]; exa.s=dis[u[t][i]]; exa.x=u[t][i]; q.push(exa); } } } } int main() { // ios::sync_with_stdio(false); // freopen("in.txt","r",stdin); int T; scanf("%d",&T); int cases = 0; while(T--){ cases++; scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++){ int ss; ll t; scanf("%lld%d",&t,&ss); for(int j=1;j<=ss;j++){ scanf("%d",&num[j]); } for(int j=1;j<=ss;j++){ u[num[j]].push_back(n+i); w[num[j]].push_back(t); u[n+i].push_back(num[j]); w[n+i].push_back(0); } } Dijkstra(1,diss1); Dijkstra(n,diss2); ll ans = INF; for(int i=1;i<=n;i++){ diss1[i]=max(diss1[i],diss2[i]); ans=min(ans,diss1[i]); } printf("Case #%d: ",cases); if(ans ==INF){printf("Evil John\n");continue;} else printf("%lld\n",ans); vector<int>anss; for(int i=1;i<=n;i++){ if(ans==diss1[i]){anss.push_back(i);} } int siz = anss.size(); for(int i=0;i<siz-1;i++){ printf("%d ",anss[i]); } printf("%d\n",anss[siz-1]); } return 0; }
∑mi=1Si≤10
如需转载,请注明出处
如有侵权,联系删除
2290713181@qq.com
如有侵权,联系删除
2290713181@qq.com