1 条题解

  • 0
    @ 2025-4-14 18:45:30

    C++ :

    /*************************************************************************
     *                                                                       *
     *                    XVII Olimpiada Informatyczna                       *
     *                                                                       *
     *   Zadanie:              Mosty (MOS)                                   *
     *   Plik:                 mos.cpp                                       *
     *   Autor:                Tomasz Kulczynski                             *
     *   Opis:                 Rozwiazanie wzorcowe.                         *
     *   Zlozonosc czasowa:    O((n + m) * m * log MAX_WIATR)                *
     *   Zlozonosc pamieciowa: O(n + m)                                      *
     *                                                                       *
     *************************************************************************/
    
    #include <cstdio>
    #include <vector>
    #include <list>
    
    #include <algorithm>
    using namespace std;
    
    const int M = 2001;
    const int N = 1001;
    const int MAX_WIATR = 1000;
    
    int n,m;
    int a[M],b[M],l[M],p[M],stopien[N];
    bool bylem[N+M];
    
    struct kraw
    {
        int x,r,c;
    };
    
    vector<kraw> v[N+M];
    
    bool sciezka(int x,int kon) //znajduje jedna sciezke powiekszajaca przeplyw
    {                           //i powieksza wzdluz niej
        if(x==kon) return 1;
        if(bylem[x]) return 0;
        bylem[x]=1;
        for(int i=0;i<(int)(v[x].size());i++) 
        {
            int y=v[x][i].x;
            if(v[x][i].c && sciezka(y,kon)) 
            {
                v[x][i].c--;
                v[y][v[x][i].r].c++;
                return 1;
            }
        }
        return 0;
    }
    
    int maxflow(int pocz,int kon)
    {
        int flow=0;
        while(1)
        {
            for(int i=0;i<=n+m+1;i++) bylem[i]=0;
            if(!sciezka(pocz,kon)) break;
            flow++;
        }
        return flow;
    }
    
    void add_edge( int a, int b, int p ) //dodaje krawedz z a do b o przepustowosci p
    {
        kraw k;
        k.x=b;
        k.r=v[b].size();
        k.c=p;
        v[a].push_back(k);
    
        k.x=a;
        k.r=v[a].size()-1;
        k.c=0;
        v[b].push_back(k);
    }
    
    void tworz(int x) //stworzenie grafu dwudzielnego, w ktorym i (1<=i<=n)
                      // jest polaczone z n+j (1<=j<=m), gdy z wierzcholka
                      // i wejsciowego grafu mozna wyjsc krawedzia j
                      // nie przekraczajac kosztu x
                      // 0 jest super-zrodlem a n+m+1 super-ujsciem
    {
        for(int i=0;i<=n+m+1;i++) 
            v[i].clear();
        for(int i=1;i<=n;i++) 
            add_edge( 0, i, stopien[i]/2 );
        for(int i=1;i<=m;i++)
        {
            if(l[i]<=x) 
                add_edge( a[i] , n+i, 1 );
            if(p[i]<=x)
                add_edge( b[i] , n+i, 1 );
            add_edge( n+i, n+m+1, 1 );
        }
    }
    
    vector<int> kr[N];
    
    void euler() //znajduje i wypisuje cykl eulera w grafie ktory jest
    {            //zapisany w listach krawedzi z kazdego wierzcholka kr[]
        if(kr[1].empty()) return;
        int g=1;
        list<int> l;
        list<int>::iterator p,q;
                
        int u=1,e;
        while(!kr[u].empty())
        {
            l.push_back(e=kr[u].back());
            kr[u].pop_back();
            u=a[e]+b[e]-u;
        }
    
        p=l.begin();
        while(p!=l.end())
        {
            q=p;
            q--;
            if(!kr[g].empty())
            {
                int u=g,e;
                while(!kr[u].empty())
                {
                    l.insert(p,e=kr[u].back());
                    kr[u].pop_back();
                    u=a[e]+b[e]-u;
                }
            }
            p=q;
            p++;
            g=a[*p]+b[*p]-g;
            p++;
        }
        for(p=l.begin();p!=l.end();++p) printf("%d ",*p);
        printf("\n");
    }
    
    int main()
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++) 
        {
            scanf("%d %d %d %d",&a[i],&b[i],&l[i],&p[i]);
            stopien[a[i]]++;
            stopien[b[i]]++;
        }
        int L=1,P=MAX_WIATR+1,S;
        while(L<P)  //wyszukiwanie binarne wyniku
        {
            S=(L+P)/2;
            tworz(S);
            if(maxflow(0,n+m+1)==m) P=S;
            else L=S+1;
        }
        if(L>MAX_WIATR) printf("NIE\n");
        else
        {
            printf("%d\n",L);
            tworz(L);
            maxflow(0,n+m+1);
            for(int i=1;i<=m;i++)
                for(int j=0;j<(int)(v[n+i].size());j++)
                    if(v[n+i][j].c) kr[v[n+i][j].x].push_back(i);
    /*** MiMi:: chyba to jest niepotrzebne
            vector<int> kl;
            for(int i=1;i<=n;i++) for(int j=0;j<(int)(kr[i].size());j++) kl.push_back(kr[i][j]);
            sort(kl.begin(),kl.end());
            for(int i=0;i<(int)(kl.size());i++) if(kl[i]!=i+1) printf("a%d\n",i);
    */
            euler();
        }
        return 0;
    }
    
    • 1

    信息

    ID
    3473
    时间
    3000ms
    内存
    128MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者