Meeting(分层图+最短路径)

Meeting

题目链接:Meeting
考点:最短路+分层图
题意:
给若干个集合,集合内的节点之间的距离是t

问从1到n 双向奔赴的最短距离。

思路比较好想:直接用 1 和 n 为起点跑两遍dijstrra。

难点是建图。每个集合节点互相连边的话要n^2 条边
每一个集合都建立一个虚拟原点,连接这一集合的所有的点。
再跑dj就可以了
代码部分:

    #include<bits/stdc++.h>
    #include <stdio.h>
    #include<numeric>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<algorithm>
    #include<math.h>
    #include <vector>
    #include<stack>
    #include<list>
    #include<set>
    #include<ctime>
    #include<queue>
    #include<utility>
    #include<map>
    #include<stdlib.h>
    #define deg(a) cout<<#a<<'='<<a<<"\n"
    #define lowbit(x)  ((x)&(-x))
    #define pll pair<int,int>
    #define int long long
    #define endl '\n'
    using namespace std;
    using i64 = long long;
    const int N = 2e6+1000;
    const int mod1 =998244353;
    const int mod2 =1e9+7;
    const int INF =0x3f3f3f3f3f3f3f;
    std::vector<pll> G[N];
    int dis1[N]={0};
    int dis2[N]={0};
  void dijkstra(int s, int *dis)//s表示起点 dis是距离数组
{
  bool vis[N];// 标记
  priority_queue<pll> ss;
  memset(vis, 0, sizeof(vis));
  dis[s] = 0;
  ss.push(make_pair(0, s));
  while(!ss.empty())
  {
    int u = ss.top().second;
    int sum = ss.top().first;
    ss.pop();
    if(vis[u])
      continue;
    vis[u] = 1;
    for(int i = 0; i < G[u].size(); i++)
    {
      int v = G[u][i].first;
      if(dis[v] > dis[u] + G[u][i].second)
      {
        dis[v] = dis[u] + G[u][i].second;
        ss.push(make_pair(-dis[v], v));
      }
    }
  }
}
    void solve(int case1)
    {  
       int n,m;
       cin>>n>>m;
       int p=n+m;  int cnt=0;
       memset(dis1,INF,sizeof dis1);
       memset(dis2,INF,sizeof dis2);
       for(int i=1;i<=1e6+1000;i++)
       {
         G[i].clear();
       }
       dis1[1]=0;
       dis2[n]=0; 
      
       for(int i=1;i<=m;i++)
       {
        int x,y;//x为边权,y为数量
        cin>>x>>y;
        for(int j=1;j<=y;j++)
        {
            int u;
            cin>>u;
            G[u].push_back({p+cnt,0});//点到虚拟原点的路径为0
            G[p+cnt].push_back({u,x});//反过来为x
//             G[p+cnt+1].push_back({p+cnt,x});
//             G[p+cnt].push_back({p+cnt+1,x});
        }
        cnt+=1;
       }
       dijkstra(1,dis1);
       dijkstra(n,dis2);
//        for(int i=1;i<=n;i++) cout<<dis1[i]<<" ";
//         cout<<endl;
//         for(int i=1;i<=n;i++) cout<<dis2[i]<<" ";
//         cout<<endl;
       int anss=1e18;
       for(int i=1;i<=n;i++)
       {
          if(dis1[i]>=1e18||dis2[i]>=1e18) continue;
          int x=max(dis1[i],dis2[i]);
          anss=min(anss,x);// cout<<anss<<" ";deg(x);
       }
       if(anss==1e18){
        cout<<"Case #"<<case1<<": Evil John"<<endl;
        return;
       }
       cout<<"Case #"<<case1<<": "<<anss<<endl;
       for(int i=1;i<=n;i++)
       {
          if(dis1[i]>=1e18||dis2[i]>=1e18) continue;
          int x=max(dis1[i],dis2[i]);
          if(x==anss) cout<<i<<' ';
       }
       cout<<endl;
 


    }
    signed main()
    {
              
      cin.tie(nullptr); 
      ios::sync_with_stdio(false);
      int kk = 1;
      cin >> kk; 
      // cin.get();
//       while(kk--) solve(kk);
      for(int i=1;i<=kk;i++) solve(i);
      return 0;
    }
          

posted @ 2023-11-07 21:11  锦林不睡觉  阅读(11)  评论(0)    收藏  举报