20180429 Mock T1 - Timing problem

【Problem Description】

A directed graph without a ring is called a directed acyclic graph, what a beautiful structure it is.

If we have a directed graph with N vertices, we may need to delete some edges to make it a directed acyclic graph. Suppose initially we only have N points that are not connected to each other, of course it is also a directed acyclic graph. Give the T edges and the direction of each edge in turn. Every time an edge is given, it is necessary to immediately decide whether to add this edge, so that this graph is always a directed acyclic graph (meaning: process each edge in order, add it if you can, let you simulate this process , the self-loop cannot be added). Calculate how many edges are not added if the requirements are met. Output 0 if all edges can join the graph.

【Input format】

The first line contains two integers: N(1<=N<=250), T(0<=T<=100,000). Next T lines, each line contains two integers x, y (1 <= x, y <= N), representing a one-way edge from x to y.

【Output format】

An integer representing the number of edges that were not added.

【Sample input】

3 6
1 2
1 3
3 1
2 1
1 2
2 3

【Example output】

2

【Example description】

1-->2, before 2-->1 there is no path, it will not cause a loop, join

1-->3, before 3-->1 there is no path, it will not cause a loop, join

3-->1, there is a path in 1-->3 before, which makes the graph have a cycle and does not join

2-->1, before 1-->2 has a path, do not join

1-->2 , there is no path for 2-->1 before, join

2-->3, there is no path for 3-->2 before, join

So the answer is 2

【Data scale】

For 40% of the data, n<=50, T<=1000

For 90% of the data, n<=150, T<=100000

For 100% of the data, n<=250, T<=100000

answer

We use \(f[i][j]\) to indicate whether \(i\) can reach \(j\) (1: yes 0: no). First ignore heavy edges. It is obviously \(O(1)\) to judge whether an edge can be added , just check whether \(f[y][x]\) is \(1\) .

If you join, you need to maintain connectivity.

As shown in the figure, for two points \(A,B\) , the circle represents the point set, the arrow represents the edge, and after connecting the edge \(A\to B\) , we need to connect the blue edge and the green edge.

It is not difficult to find that we can combine \(A\) with the blue set, \(B\) with the green set, so the problem becomes:

The blue set connects to the green set.

The blue set is the point set that can reach \(A\) ; the green set represents the point set that can reach \(B\) .

\(n^2\) Vigorously connect the sides.

my code

#include <cstring>
#include <fstream>

using namespace std;

ifstream fin("stock.in");
ofstream fout("stock.out");

const int maxm=100000;
const int maxn=256;

int a[maxn][maxn];
int b[maxm],c[maxm];

int main()
{
    int n, m;
    fin >> n >> m;
    int ans=0;
    for(int i=0; i<m; ++i)
    {
        int aa, bb;
        fin >> aa >> bb;
        if(aa==bb || a[bb][aa]) ans++;
        else
        {
            int k1=0;
            int k2=0;
            b[++k1]=aa;
            c[++k2]=bb;
            for(int j=1; j<=n; ++j)
                if(a[j][aa] && !a[j][bb])
                    b[++k1]=j;
            for(int j=1; j<=n; ++j)
                if(a[bb][j] && !a[aa][j])
                    c[++k2]=j;
            for(int j=1; j<=k1; ++j)
                for(int k=1; k<=k2; ++k)
                    a[b[j]][c[k]]=1;
        }
    }
    fout << ans << '\n';
    return 0;
}

bitset optimization

The above code is passable, but you can also use bitset to optimize it.

#include <iostream>
#include <bitset>
#include <cstdio>

using namespace std;

typedef int ll;

inline char gc()
{
    static char buf[1<<14],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}

#define dd c=gc()
inline ll read()
{
    ll x=0,f=1;
    char dd;
    for(; !isdigit(c); dd)if(c=='-')f=-1;
    for(; isdigit(c); dd)x=(x<<1)+(x<<3)+(c^48);
    return x*f;
}
#undef dd

inline void write(ll x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10|48);
}

bitset<252>a[252];

int main()
{
    freopen("stock.in","r",stdin);
    freopen("stock.out","w",stdout);
    register ll n=read(),ans=0;
    for (register ll i=0; i<n; ++i) a[i][i]=1;
    for (register ll m=read(),x,y; m; --m)
    {
        x=read()-1,y=read()-1;
        if (a[y][x]) ++ans;
        else if (!a[x][y])
            for (register ll i=0; i<n; ++i)
            {
                if (a[i][x]) a[i]=a[i]|a[y];
            }
    }
    return write(ans),0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325092860&siteId=291194637