zoukankan      html  css  js  c++  java
  • bzoj 4289 TAX —— 点边转化

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4289

    把边转化成点,同一个原有点相连的边中,边权小的向大的连差值的边,大的向小的连0的边;

    一开始想的是给每个新点记一个点权是这个点(边)原来的权,走到它时先加上点权,因为要在原图上经过这条边还是要花费边权;

    但是这样在原图中的边之间转移时会把它们的边权都加上,就不对了;

    所以应该是把原图的边进一步拆成两个点,两端点的集合各加入一个,这两点之间连原边权的边;

    题目上什么也没说...总之 dis 是 long long 的;

    如果直接把刚才存边用的结构体放进 queue,就要注意把结构体的 w 定义成 ll,而且一定注意结构体内部定义变量的顺序!因为 (N){..., ...} 的写法是强调顺序的!

    ——然后发现这道题三个月前做过-_- https://www.cnblogs.com/Zinn/p/9326302.html

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    int const xn=2e5+5,xm=1e5+5;
    int n,m,s,t,hd[xn<<1],ct,to[xn<<3],nxt[xn<<3],w[xn<<3];
    ll dis[xn<<1];
    bool vis[xn<<1];
    struct N{
      ll w; int id;//ll(dis)
      bool operator < (const N &y) const
      {return w<y.w;}
    };
    vector<N>v[xm];
    priority_queue<N>q;
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
    void dij()
    {
      while(q.size())
        {
          int x=q.top().id; q.pop();
          if(vis[x])continue; vis[x]=1;
          for(int i=hd[x],u;i;i=nxt[i])
        {
          if(dis[u=to[i]]>dis[x]+w[i])
            dis[u]=dis[x]+w[i],q.push((N){-dis[u],u});
        }
        }
    }
    int main()
    {
      n=rd(); m=rd(); s=0; t=2*m+1;
      for(int i=1,x,y,z;i<=m;i++)
        {
          x=rd(); y=rd(); z=rd();
          v[x].pb((N){z,i}); v[y].pb((N){z,i+m});
          add(i,i+m,z); add(i+m,i,z);
        }
      for(int i=0;i<v[1].size();i++)add(s,v[1][i].id,v[1][i].w);
      for(int i=0;i<v[n].size();i++)add(v[n][i].id,t,0);//0
      for(int i=1;i<=n;i++)
        {
          sort(v[i].begin(),v[i].end());
          for(int j=1;j<v[i].size();j++)
        add(v[i][j-1].id,v[i][j].id,v[i][j].w-v[i][j-1].w),add(v[i][j].id,v[i][j-1].id,0);
        }
      memset(dis,0x3f,sizeof dis);
      dis[s]=0; q.push((N){0,s});
      dij(); 
      printf("%lld
    ",dis[t]);
      return 0;
    }
  • 相关阅读:
    Ubuntu adb devices :???????????? no permissions (verify udev rules) 解决方法
    ubuntu 关闭显示器的命令
    ubuntu android studio kvm
    ubuntu 14.04版本更改文件夹背景色为草绿色
    ubuntu 创建桌面快捷方式
    Ubuntu 如何更改用户密码
    ubuntu 14.04 返回到经典桌面方法
    ubuntu 信使(iptux) 创建桌面快捷方式
    Eclipse failed to get the required ADT version number from the sdk
    Eclipse '<>' operator is not allowed for source level below 1.7
  • 原文地址:https://www.cnblogs.com/Zinn/p/9802183.html
Copyright © 2011-2022 走看看