E - E CodeForces - 1100E (+ 반 위상 정렬)

E - E CodeForces - 1100E

N은 방향 그래프 노드가 상기 노드 1부터 n까지 번호가 단방향 에지의 존재를 해요. 각각의 에지가 그 방향을 반전하는 데 필요한 비용의 대신에, 중량 멀다. 도는 비순환 그래프 최대 에지 플립 작은 가중 방식, 플립 방식의 최대 우측으로 확인하고자.

입력의 입력 단일 세트는, 제 라인은 두 정수 n 및 m 세 정수의 (2≤n≤100 000,1≤m≤100 000) 다음의 m 행을 포함 u_i, V_I
, W_i. (1 <= u_i, V_I는 <= N- ,. 1 <= W_i <=
10 ^. 9), (V)에 U가 도로 w의 중량을 나타내고있다. 도로 번호 1의 처음부터. 루프백 없음.

두 개의 정수 첫번째 라인 출력 출력은 바로 위의 측면과도 (k)의 수를 반전 할 필요가 반전한다. k는 최소한의 필요는 없다.

다음 라인 출력 k- 스페이스에 플립도 요구의 수를 나타내는 정수 구분

많은 솔루션이있는 경우, 그 중 하나를 인쇄 할 수 있습니다.

Examples
Input
5 6
2 1 1
5 2 6
2 3 2
3 4 3
4 5 5
1 5 4
Output
2 2
1 3 
Input
5 7
2 1 5
3 2 3
1 3 3
2 4 1
4 3 5
5 4 1
1 5 3
Output
3 3
3 4 7 

사고

  • 제목의 의미 : 최소 무게 반전이 얼마나 전체를 변경하는 데 필요한 물어 동안 나에게 가중치에지도를주고,이 그림은, 반지있을 수 있습니다?
  • 아이디어 : 제 이진 열거하여, 최소 반전 중간 오른쪽에 최대 측 에지의 우측 에지의 도면을 부여 덜 중앙보다 나머지이어서, 양방향 에지 (존재하지 않음)을 고려 실행 측면 위상 종류에 따라도 아이가있는 경우이 반지는, 그래서 난 중간 + 1, 그렇지 않으면 R =하자 = 중순 여부를 확인합니다 - 1
  • 링크

문제 해결

#include<iostream>
#include<cmath>
#include<cstdio>
#include<queue>
#include<cstring>
#define int long long
#define inf 10000000000000
using namespace std;
int read(){
    int res=0;char ch=0;
    while (!isdigit(ch))ch=getchar();
    while (isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}

const int N=1000100;
struct EDGE{
    int ver,nxt,dis,pre;
}edge[N];
int n,m,cnt,head[N],vis[N],d[N],ans[N],dfn[N],dfs_cnt;

void add(int u,int v,int t){
    edge[++cnt].ver=v;
    edge[cnt].nxt=head[u];
    edge[cnt].dis=t;
    edge[cnt].pre=u;
    head[u]=cnt;
}

queue<int>q;
bool check(int x){

    memset(d,0,sizeof(d));memset(vis,0,sizeof(vis));

    for (int i=1;i<=m;i++)if(edge[i].dis>x)d[edge[i].ver]++;

    for (int i=1;i<=n;i++)if (!d[i])q.push(i);

    while (!q.empty()){

        int u=q.front();q.pop();

        for (int i=head[u];i;i=edge[i].nxt)
        {
            if (edge[i].dis<=x)continue;

            int v=edge[i].ver;d[v]--;if (!d[v])q.push(v);
        }
    }

    for (int i=1;i<=n;i++)if (d[i])return 0;

    return 1;
}
void solute(int x){
    memset(d,0,sizeof(d));memset(vis,0,sizeof(vis));

    for (int i=1;i<=m;i++)if(edge[i].dis>x)d[edge[i].ver]++;
    for (int i=1;i<=n;i++)if (!d[i])q.push(i);

    while (!q.empty())
    {
        int u=q.front();q.pop();dfn[u]=++dfs_cnt;

        for (int i=head[u];i;i=edge[i].nxt)
        {
            if (edge[i].dis<=x)continue;
            int v=edge[i].ver;d[v]--;if (!d[v])q.push(v);
        }
    }

    for (int i=1;i<=m;i++){
        if (edge[i].dis<=x){
            int u=edge[i].pre,v = edge[i].ver;
            if (dfn[u]>dfn[v])ans[++cnt]=i;
        }
    }
}
signed main(){
    n=read();m=read();
    for (int i=1;i<=m;i++){
        int x=read(),y=read(),t=read();add(x,y,t);
    }
    int l=0,r=inf;
    while (l<r)
    {
        int mid=l+r>>1;
        if (check(mid))
            r=mid;
        else
            l=mid+1;
    }

    cnt=0;
    solute(r);
    printf("%lld %lld\n",r,cnt);
    for (int i=1;i<=cnt;i++){
        printf("%lld ",ans[i]);
    }
}

추천

출처www.cnblogs.com/lql-nyist/p/12629446.html