• 刷题总结——做运动(NOIP模拟)


    题目:

      给定一个无向图,节点数n<=50000,m<=1000000,每条边有两个值t和c,边的长度为t*c···现在要求再t尽量小的情况下,求两节点st的最短距离

    题解:

      第一次做的时候想都没有想直接用二分+迪杰斯特拉了···哎连复杂度都算不来了···

      正解应该是将边按t升序排序后跑kruskals····用并差集判st是否连通··一旦联通将t值小于等于目前枚举的t值的边全部加入建图然后跑最短路就可以了···

      其实如果考试时仔细想一想时是可以想到正解的··毕竟如果t要尽量小的话不是二分就是最小生成树了···但并差集判连通性这一点已经很久每用过了··这题算是提了醒吧··

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<queue>
    using namespace std;
    priority_queue< pair<long long,int> >que;
    const int N=5e5+5;
    const int M=1e6+5;
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())  f=(f<<3)+(f<<1)+c-'0'; 
      return f;
    }
    struct node
    {
      int x,y,T,C;
      inline friend bool operator < (node a,node b)
      {
        return a.T<b.T;
      }
    }edge[M]; 
    int Father[N],fst[N],go[M*2],nxt[M*2],n,m,src,des,anst,tot;
    long long dis[N],val[M*2];
    inline bool comb(int a,int b,int c,int d)
    {
      nxt[++tot]=fst[a],fst[a]=tot,go[tot]=b,val[tot]=(long long)c*d;
      nxt[++tot]=fst[b],fst[b]=tot,go[tot]=a,val[tot]=(long long)c*d;
    }
    inline int get(int a)
    {
      if(Father[a]==a)  return a;
      else return Father[a]=get(Father[a]);
    }
    inline void solve()
    {
      for(register int i=1;i<=n;i++)  dis[i]=2e+18;
      dis[src]=0;que.push(make_pair(0,src));
      while(!que.empty())
      {
        int u=que.top().second;que.pop();
        if(u==des)  break; 
        for(register int e=fst[u];e;e=nxt[e])
        {
          int v=go[e];
          if(dis[v]>dis[u]+val[e])
          {
            dis[v]=dis[u]+val[e]; 
            que.push(make_pair(-dis[v],v));
          }
        }
      }
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      n=R();m=R();  
      for(register int i=1;i<=n;i++)  Father[i]=i;
      for(register int i=1;i<=m;i++)  edge[i].x=R(),edge[i].y=R(),edge[i].T=R(),edge[i].C=R();
      src=R();des=R();
      sort(edge+1,edge+m+1);
      for(register int i=1;i<=m;i++)
      {
        int fx=get(edge[i].x),fy=get(edge[i].y);
        Father[fx]=fy;
        if(get(src)==get(des))  
        {
          anst=edge[i].T;
          break;
        }
      }
      cout<<anst<<" ";
      for(register int i=1;i<=m;i++)
      {
        if(edge[i].T>anst)  break;
        comb(edge[i].x,edge[i].y,edge[i].T,edge[i].C);
      }
      solve();cout<<dis[des]<<endl;
      return 0;
    }
  • 相关阅读:
    课堂练习02
    第五周进度条
    软件工程个人作业03
    第四周进度条
    构建之法阅读笔记02
    ---JS canvas学习笔记
    JavaScript 对象、DOM对象、jquery对象的区别、转换详解
    JQM---列车时刻查询
    JS---如何避免用户在请求时“猛击”
    HTML5 新增属性和废除属性
  • 原文地址:https://www.cnblogs.com/AseanA/p/7737238.html
Copyright © 2020-2023  润新知