July 23, 2019 (graph theory)

Most water wave test! ! !

And the water looks like.
Just take some \ (sb \) points, the other to \ (jj \) a. The most depressing is \ (T1 \) , the water back and forth more than two hours did not \ (yy \) out, depressed ah! ! ! !

Or start with the simplest of talk:

prob2: problem tree (tree)

Title effect: given an unrooted trees, were \ (m \) a query, each given \ (A \) and \ (B \) , all forms of such tree seeking \ (A \) is \ (B \) ancestor or \ (B \) is (a \) \ ancestor program number.

\ (sb \) questions, simply get points, the typical red title. Obtaining \ (A \) and \ (B \) of \ (LCA \) , judgment \ (A \) and \ (B \) is equal to \ (LCA \) , then classification regulation by both the sub- tree \ (size \) calculate the answer

Look at the code:

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define xx 210000
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
vector<int>e[xx];
struct point{ll sz,top,dep,fa,son;bool vis;}dot[xx];
inline void dfs1(int g)
{
    dot[g].sz=1;
    fur(i,0,(int)e[g].size()-1)
    {
        if(!dot[e[g][i]].vis)
        {
            dot[e[g][i]].vis=true;
            dot[e[g][i]].fa=g;
            dot[e[g][i]].dep=dot[g].dep+1;
            dfs1(e[g][i]);
            dot[g].sz+=dot[e[g][i]].sz;
            if(dot[dot[g].son].sz<dot[e[g][i]].sz) dot[g].son=e[g][i];
        }
    }
}
inline void dfs2(int g,int gg)
{
    dot[g].top=gg;
    if(dot[g].son) dfs2(dot[g].son,gg);
    fur(i,0,(int)e[g].size()-1) if(e[g][i]!=dot[g].son&&e[g][i]!=dot[g].fa) dfs2(e[g][i],e[g][i]);
}
inline int lca(int u,int v)
{
    while(dot[u].top!=dot[v].top)
    {
        if(dot[dot[u].top].dep<dot[dot[v].top].dep) swap(u,v);
        u=dot[dot[u].top].fa;
    }
    if(dot[u].dep<dot[v].dep) return u;
    else return v;
}
inline int llca(int u,int v)
{
    int before;
    while(dot[u].top!=dot[v].top) before=v,v=dot[dot[v].top].fa;
    if(v!=u) return dot[u].son;
    else return dot[before].top;
}
int main()
{
    int n=in,m=in;
    fur(i,1,n-1)
    {
        int x=in,y=in;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dot[1].vis=true;
    dfs1(1);
    dfs2(1,1);
    fur(i,1,m)
    {
        int x=in,y=in;
        int z=lca(x,y);
        if(z!=x)
        {
            if(z!=y) printf("%lld\n",dot[x].sz+dot[y].sz);
            else printf("%lld\n",n-dot[llca(y,x)].sz+dot[x].sz);
        }
        else printf("%lld\n",n-dot[llca(x,y)].sz+dot[y].sz);
    }
    return 0;
}

prob3: Feast (party)

Title effect: Given a connected graph, and a given fixed point and two pairs of fixed length, deleting as many edges such that the shortest path between the fixed point does not exceed the fixed length, up to the output side deleted.

\ (My \) \ (solutin \) : Well, I think this question is simpler, when the examination-half write wilt, the results did not ran, only the water \ (50 \) points. Originally thought might \ (T \) to fly, but later found good results. While the complexity and correctness completely wrong, but the data can take this water to half the points if the exam, then a wave of border violence should be able after (but the fact is there will be a part of \ (T \) to fly, is expected to score \ (70 \) or so), tired heart, on the code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define xx 3300
#define inf 0x7f
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
int dis1[xx],dis2[xx],pre1[xx],pre2[xx];
vector<int>e[xx];
bool lt[xx][xx],vis1[xx],vis2[xx],key;
int id[xx][xx],pk[xx];
deque<int>q;
inline void spfa(int s,int *dis,bool *vis,int *pre)
{
    dis[s]=0;
    vis[s]=true;
    q.push_back(s);
    while(!q.empty())
    {
        int g=q.front();
        vis[g]=false;
        q.pop_front();
        fur(i,0,(int)e[g].size()-1)
        {
            if(lt[g][e[g][i]])
            {
                if(dis[e[g][i]]>dis[g]+1)
                {
                    dis[e[g][i]]=dis[g]+1;
                    pre[e[g][i]]=g;
                    if(!vis[e[g][i]])
                    {
                        vis[e[g][i]]=true;
                        if(!q.empty())
                        {
                            if(dis[e[g][i]]<=dis[q.front()]) q.push_front(e[g][i]);
                            else q.push_back(e[g][i]);
                        }
                        q.push_back(e[g][i]);
                    }
                }
            }
        }
    }
}
struct edge{int id,u,v,num;}ee[xx<<1];
inline void init()
{
    memset(dis1,inf,sizeof(dis1));
    memset(dis2,inf,sizeof(dis2));
    memset(pre1,0,sizeof(pre1));
    memset(pre2,0,sizeof(pre2));
    memset(vis1,false,sizeof(vis1));
    memset(vis2,false,sizeof(vis2));
}
inline bool cmp(edge x,edge y){return x.num<y.num;}
inline void handle(int t1,int t2,int all)
{
    while(pre1[t1])
    {
        ee[id[pre1[t1]][t1]].num++;
        t1=pre1[t1];
    }
    while(pre2[t2])
    {
        ee[id[pre2[t2]][t2]].num++;
        t2=pre2[t2];
    }
    sort(ee+1,ee+all+1,cmp);
}
inline bool check(int now,int s1,int s2,int t1,int t2,int l1,int l2)
{
    fur(i,1,now)
    {
        lt[ee[i].u][ee[i].v]=false;
        lt[ee[i].v][ee[i].u]=false;
    }
    init();
    spfa(s1,dis1,vis1,pre1);
    spfa(s2,dis2,vis2,pre2);
    fur(i,1,now)
    {
        lt[ee[i].u][ee[i].v]=true;
        lt[ee[i].v][ee[i].u]=true;
    }
    if(dis1[t1]>l1||dis2[t2]>l2) return false;
    else return true;
}
inline bool checked(int *u,int now,int s1,int s2,int t1,int t2,int l1,int l2)
{
    fur(i,1,now)
    {
        lt[ee[u[i]].u][ee[u[i]].v]=false;
        lt[ee[u[i]].v][ee[u[i]].u]=false;
    }
    init();
    spfa(s1,dis1,vis1,pre1);
    spfa(s2,dis2,vis2,pre2);
    fur(i,1,now)
    {
        lt[ee[u[i]].u][ee[u[i]].v]=true;
        lt[ee[u[i]].v][ee[u[i]].u]=true;
    }
    if(dis1[t1]>l1||dis2[t2]>l2) return false;
    else return true;
}
inline void ck(int m,int now,int here,int need,int s1,int s2,int t1,int t2,int l1,int l2)
{
    if(key) return;
    if(now==need)
    {
        if(checked(pk,now,s1,s2,t1,t2,l1,l2)) key=true;
        return;
    }
    fur(i,here,m)
    {
        pk[now+1]=i;
        if(now+1+m-i<need) return;
        ck(m,now+1,here+1,need,s1,s2,t1,t2,l1,l2);
    }
}
int main()
{
    int n=in,m=in,all=0;
    fur(i,1,m)
    {
        int x=in,y=in;
        e[x].push_back(y);
        e[y].push_back(x);
        lt[x][y]=true;
        lt[y][x]=true;
        id[y][x]=id[x][y]=++all;
        ee[all].u=x;
        ee[all].v=y;
        ee[all].id=all;
        ee[all].num=0;
    }
    int s1=in,t1=in,l1=in;
    int s2=in,t2=in,l2=in;
    init();
    spfa(s1,dis1,vis1,pre1);
    spfa(s2,dis2,vis2,pre2);
    if(dis1[t1]>l1||dis2[t2]>l2)
    {
        printf("That's all trouble!\n");
        return 0;
    }
    handle(t1,t2,all);
    int ans=0,L=0,R=m;
    while(L<R)
    {
        int mid=(L+R)>>1;
        if(check(mid,s1,s2,t1,t2,l1,l2)) ans=mid,L=mid+1;
        else R=mid-1;
    }
    ck(m,0,1,ans+1,s1,s2,t1,t2,l1,l2);
    if(key) ans++;
    printf("%d\n",ans);
    return 0;
}

Positive solutions : first \ (orz \) seniors wave

Thought very clever, obtaining a given path between two points on \ (dis (s1, t1) \) and $
DIS (S2, T2) \ (, provided there is an overlap portion between the two \) P1 \ (and \) P2 \ (, then we request is \) DIS (S1, T1)
+ DIS (S2, T2), DIS (P1, P2) $ minimum (since the right side are \ (1 \) , so use Save the total number of edges above
expressions can be deleted to obtain the number of edges, so that the expression maximum is minimum), so that the subject was much easier

On the code:

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define xx 3100
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
int dis[xx][xx],vis[xx];
queue<int>q;
vector<int>e[xx];
inline void bfs(int s)
{
    dis[s][s]=0;
    vis[s]=s;
    q.push(s);
    while(!q.empty())
    {
        int g=q.front();
        q.pop();
        fur(i,0,(int)e[g].size()-1)
        {
            if(vis[e[g][i]]!=s)
            {
                dis[s][e[g][i]]=dis[s][g]+1;
                vis[e[g][i]]=s;
                q.push(e[g][i]);
            }
        }
    }
}
int main()
{
    int n=in,m=in;
    fur(i,1,m)
    {
        int x=in,y=in;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    memset(dis,0x7f,sizeof(dis));
    fur(i,1,n) bfs(i);
    int s1=in,t1=in,l1=in;
    int s2=in,t2=in,l2=in;
    if(dis[s1][t1]>l1||dis[s2][t2]>l2)
    {
        puts("That's all trouble!");
        return 0;
    }
    int ans=dis[s1][t1]+dis[s2][t2];
    fur(i,1,n)
    {
        fur(j,1,n)
        {
            if(dis[i][j]+dis[s1][i]+dis[j][t1]<=l1&&dis[i][j]+dis[j][t2]+dis[s2][i]<=l2)
                ans=min(ans,dis[i][j]+dis[s1][i]+dis[j][t1]+dis[j][t2]+dis[s2][i]);
            if(dis[j][i]+dis[s1][j]+dis[i][t1]<=l1&&dis[j][i]+dis[s2][i]+dis[j][t2]<=l2)
                ans=min(ans,dis[j][i]+dis[s1][j]+dis[s2][i]+dis[i][t1]+dis[j][t2]);
        }
    }
    printf("%d\n",m-ans);
    return 0;
}

Of course, the procedure described above is preferably used instead of the adjacency list \ (Vector \) , the examination \ (Vector \) there is the risk of the card

prob1: counting points (XDIS)

Title effect: Given an undirected graph, the right side edge strip, wherein one point to another through the right side of the cost of a path is defined as the maximum value of the path, and the shortest one point to another at the expense of the minimum , find the shortest length \ (X \) is the number of points

Positive solutions : a wave sigh again \ (ljq \) intelligence chiefs, and he was deeply impressed me

The right side of the question are integers, and although the length \ (x \) is not directly seeking, but to get a length of no more than \ (x \) but well out (larger than \ (x \) side are omitted, the size of the block is calculated Unicom remaining side is formed, if the block size is a link \ (cnt_i \) , then brought \ (C_ {cnt_i} ^ 2 \) contribution to think about it, this is not difficult to prove right), so you can first calculate the shortest path is not greater than \ (x \) is the number of points, then calculate the shortest path is not greater than \ (x-1 \) point to the number, easy to solve.

I also went on the results of the examination room to run what \ (SPFA \) , also blind push a wave of what formula, the final surface \ (T \) fly, no \ (T \) is also full of \ (WA \) ......

Do not say, sadly, on the code (or too much food, and just have a disjoint-set tone for a long time):

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define xx 330000
#define ll long long
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
struct edge{ll u,v,val;}d[xx];
ll fa[xx],n,m,cnt[xx];
inline ll find(int x){return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
inline bool cmp(edge x,edge y){return x.val<y.val;}
inline ll sol(ll x)
{
    fur(i,1,n) fa[i]=i,cnt[i]=0;
    fur(i,1,m)
    {
        if(d[i].val>x) break;
        if(find(fa[d[i].u])!=find(fa[d[i].v])) fa[find(d[i].u)]=find(d[i].v);
    }
    fur(i,1,n) cnt[find(i)]++;
    ll res=0;
    fur(i,1,n) if(cnt[i]) res+=cnt[i]*(cnt[i]-1)/2;
    return res;
}
int main()
{
    n=in,m=in;
    ll k=in;
    fur(i,1,m)
    {
        ll x=in,y=in,z=in;
        d[i]=(edge){x,y,z};
    }
    sort(d+1,d+m+1,cmp);
    ll ans1=sol(k);
    ll ans2=sol(k-1);
    printf("%lld\n",ans1-ans2);
    return 0;
}

note! note! High-energy front

However, the most difficult problem there is the most water of data (so this question is actually not so disgusting).

prob4: Minimum Spanning Tree (Graph)

Title effect: I began to have a \ (n-\) nodes, there is no side in FIG, after m operations, a total of three kinds, the operation number is set \ (I \) , the first \ (ADD (a, B) \) as (a, b \) \ add a length of between \ (I \) side, a second \ (dELETE (k) \) is a front delete \ (K \) major sides, and finally one kind \ (the RETURN \) , for avoidance of \ (i-1 \) key operation, to ensure that the operation is not \ (the RETURN \) . After each operation of the output side of the sum of the weights of FIG minimum spanning tree, without the minimum spanning tree, output \ (0 \)

Began to want to do with monotonous queue, the result \ (CE \) , but unfortunately ......

Later seniors saySuckerTitle, the idea is very simple, just like that I found (shameless). But then he did not put into practice because of lack of time (both engage in \ (T1 \) , ah !!).

Impotent rage ......

Or speak to the bar, positive solutions : First, to clear three properties: \ (1 \) if one side has not been selected minimum spanning tree when they join, he will never be selected; \ (2 \) deleted puncturing only added last edge \ (K \) edges; \ (3 \) returns only return to the previous version. Generally help solve problems on the three, but also because this problem does not require compulsory online, then a clear template arise: first recorded answer every moment, because the plus side does not affect the spanning tree after forming, so before use It does not affect the correctness of the answer, and the edge can be discarded (remember \ (Tag \) ), yet when the spanning tree molding, the violent run; Erase state will be reduced to the addition of the last \ (K \) edges before state, the answer has been recorded, so with the answer; revoked the earlier record is good, plus revocation on the first side plus side, re-run of violence, then pop up, the border erase revoked and they can \ (yy \) out, both of which are previously available The answer instead. \ (ljq \) said: "The difficulty is not large."

Main points: disjoint-set optimization of the two - by rank merger

By subtree \ (size \) the magnitude metaphysical tree in order to achieve high compression to save time

(Tucao look, there are data \ (30 \) sub-parts division (only \ (ADD \) operations), but to lay the code for this operation may be too \ (90 \) points, this data was simply unable to Tucao water,McCaw, Looked at a sample answer seems to be \ (m \) a \ (0 \) , for this data and I had \ (CE \) , died on the spot ......)

On the code:

#include<iostream>
#include<cstdio>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i+=1)
#define ll long long
#define xx 500010
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
ll fa[xx],sta[xx],ans[xx],id[xx],sz[xx];
bool choose[xx];
struct prom{ll u,v,op,k;}b[xx];
inline ll find(ll x){return fa[x]?find(fa[x]):x;}
int main()
{
    ll n=in,m=in,top=0,cnt=0,length=0;
    char ch[10];
    fur(i,1,n) sz[i]=1;
    fur(i,1,m)
    {
        scanf("%s",ch);
        if(ch[0]=='R') b[i].op=3;
        if(ch[0]=='A') b[i].op=1,b[i].u=in,b[i].v=in;
        if(ch[0]=='D') b[i].op=2,b[i].k=in;
    }
    fur(i,1,m)
    {
        if(b[i].op==1)
        {
            ll a=find(b[i].u),c=find(b[i].v);
            if(sz[a]>sz[c]) swap(a,c);
            id[++top]=i;
            sta[top]=a;
            if(a!=c)
            {
                fa[a]=c;
                sz[c]+=sz[a];
                ++cnt;
                length+=i;
                choose[i]=true;
            }
            if(cnt>=n-1) ans[i]=length;
        }
        if(b[i].op==2)
        {
            if(b[i+1].op!=3)
            {
                fur(j,1,b[i].k)
                {
                    if(choose[id[top]])
                    {
                        --cnt;
                        length-=id[top];
                        sz[fa[sta[top]]]-=sz[sta[top]];
                        fa[sta[top]]=0;
                    }
                    top-=1;
                }
                if(cnt>=n-1) ans[i]=length;
            }
            else ans[i]=ans[id[i-b[i].k+1]-1];
        }
        if(b[i].op==3)
        {
            if(b[i-1].op==1)
            {
                if(choose[id[top]])
                {
                    --cnt;
                    length-=id[top];
                    sz[fa[sta[top]]]-=sz[sta[top]];
                    fa[sta[top]]=0;
                }
                top-=1;
            }
            ans[i]=ans[i-2];
        }
        printf("%lld\n",ans[i]);
    }
    return 0;
}

This unexpected solution to a problem written long ah, hope to stop \ (dabai \) a

Guess you like

Origin www.cnblogs.com/ALANALLEN21LOVE28/p/11312981.html