• E. Andrew and Taxi(二分+拓扑判环)


    题目链接:http://codeforces.com/contest/1100/problem/E

    题目大意:给你n和m,n代表有n个城市,m代表有m条边,然后m行输入三个数,起点,终点,花费。,每一条边的花费指的是将这条路方向反转的花费。然后问你使得整个图没有环的最小花费。(这里的最小花费指的是改变方向的边中,权值最大的那个)。

    具体思路:二分答案,我们找出符合题目条件的最优解,check的时候,建立边权大于当前值的边,我们是通过形成的图判断有没有环来检验的,找到最优解之后,将剩余边权的大于最优解的边建立一个图,然后进行拓扑排序。再枚举每一条边,看这一条边的起点和终点的拓扑序,如果说起点的拓扑序大于终点的拓扑序,也就是说这条边应该是方向翻转,然后找出这满足情况的边就可以了。

    反思:

    1.这样为什么可以呢?昨晚打比赛的时候想到了一种情况,就是如果将当前的一条边翻转之后,原来的图中的环会不再存在,但是会形成新的图,这样的话也是不行的,但是对于这种情况,画画图就知道了,这种情况的话,外面肯定是有一个大环的,我们只需要对这个大环进行操作就可以了(操作的边数没有限制,只要这条边权比当前二分的值小就可以了)。

    AC代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cmath>
      5 #include <cstring>
      6 #include <ctime>
      7 #include <algorithm>
      8 #include <map>
      9 #include <vector>
     10 #include <queue>
     11 using namespace std;
     12 # define ll long long
     13 # define pi acos(-1.0)
     14 const int maxn  = 1e5+100;
     15 int deg[maxn],head[maxn],ord[maxn],vis[maxn];
     16 int num,n,m;
     17 vector<int>qq;
     18 struct node
     19 {
     20     int fr;
     21     int to;
     22     int nex;
     23     int cost;
     24 } q[maxn],edge[maxn*2];
     25 void init()
     26 {
     27     num=0;
     28     memset(head,-1,sizeof(head));
     29     memset(deg,0,sizeof(deg));
     30 }
     31 void addedge(int fr,int to)
     32 {
     33     edge[num].to=to;
     34     edge[num].nex=head[fr];
     35     head[fr]=num++;
     36     deg[to]++;
     37 }
     38 bool check(int t)
     39 {
     40     memset(vis,0,sizeof(vis));
     41     init();
     42     for(int i=1; i<=m; i++)
     43     {
     44         if(q[i].cost>t)
     45             addedge(q[i].fr,q[i].to);
     46     }
     47     queue<int>wakaka;
     48     for(int i=1;i<=n;i++){
     49     if(deg[i]==0){
     50     wakaka.push(i);
     51     }
     52     }
     53     while(!wakaka.empty()){
     54     int top=wakaka.front();
     55     wakaka.pop();
     56     vis[top]=1;
     57     for(int i=head[top];i!=-1;i=edge[i].nex){
     58     int u=edge[i].to;
     59     if(--deg[u]==0)wakaka.push(u);
     60     }
     61     }
     62     for(int i=1;i<=n;i++){
     63     if(vis[i]==0)return false;//(拓扑判环)
     64     }
     65     return true;
     66 }
     67 int main()
     68 {
     69     scanf("%d %d",&n,&m);
     70     for(int i=1; i<=m; i++)
     71     {
     72         scanf("%d %d %d",&q[i].fr,&q[i].to,&q[i].cost);
     73     }
     74     int l=0,r=1e9;
     75     while(l<r)
     76     {
     77         int mid=(l+r)/2;
     78         if(check(mid))
     79         {
     80             r=mid;
     81         }
     82         else
     83             l=mid+1;
     84     }
     85     init();
     86     for(int i=1; i<=m; i++)
     87     {
     88         if(q[i].cost>r)
     89         {
     90             addedge(q[i].fr,q[i].to);
     91         }
     92     }
     93     queue<int>wakaka;
     94     for(int i=1; i<=n; i++)
     95     {
     96         if(!deg[i])
     97             wakaka.push(i);
     98     }
     99     memset(ord,0,sizeof(ord));
    100     int ans=0;
    101     while(!wakaka.empty())
    102     {
    103         int top=wakaka.front();
    104         wakaka.pop();
    105         ord[top]=++ans;
    106         for(int i=head[top]; i!=-1; i=edge[i].nex)
    107         {
    108             int to=edge[i].to;
    109             deg[to]--;
    110             if(!deg[to])
    111             {
    112                 wakaka.push(to);
    113             }
    114         }
    115     }
    116     for(int i=1; i<=m; i++)
    117     {
    118         if(ord[q[i].fr]>ord[q[i].to])//(拓扑序)
    119         {
    120             qq.push_back(i);
    121         }
    122     }
    123     printf("%d %d
    ",r,qq.size());
    124     int len=qq.size();
    125     for(int i=0; i<len; i++)
    126     {
    127         if(i==0)
    128             printf("%d",qq[i]);
    129         else
    130             printf(" %d",qq[i]);
    131     }
    132     printf("
    ");
    133     return 0;
    134 }
  • 相关阅读:
    SQL Server 错误15401:没有找到Windows NT用户或组‘EMLE\ASPNET’
    使用 TestContext 类
    C# 动态2维数组
    2010年春季 软件测试技术 软件项目管理 实验安排
    代码覆盖率结果:没有为此测试运行启用代码覆盖率
    InternetGetCookie/InternetSetCookie (WinInet) changed with Internet Explorer 7
    C# 替换文本文件中的某一行 (要求此文件存在)
    android 复制 粘贴 功能实现
    java动态代理(JDK和cglib)
    使用ant打web应用更新包
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10266062.html
Copyright © 2020-2023  润新知