Sunday, 17 January 2016

**Civilization


Civilization

Andrew plays a game called "Civilization". Dima helps him.
The game has n cities and m bidirectional roads. The cities are numbered from 1 to n. Between any pair of cities there either is a single (unique) path, or there is no path at all. A path is such a sequence of distinct cities v1, v2, ..., vk, that there is a road between any contiguous cities vi and vi + 1 (1 ≤ i < k). The length of the described path equals to (k - 1). We assume that two cities lie in the same region if and only if, there is a path connecting these two cities.
During the game events of two types take place:
  1. Andrew asks Dima about the length of the longest path in the region where city x lies.
  2. Andrew asks Dima to merge the region where city x lies with the region where city y lies. If the cities lie in the same region, then no merging is needed. Otherwise, you need to merge the regions as follows: choose a city from the first region, a city from the second region and connect them by a road so as to minimize the length of the longest path in the resulting region. If there are multiple ways to do so, you are allowed to choose any of them.
Dima finds it hard to execute Andrew's queries, so he asks you to help him. Help Dima.
Input
The first line contains three integers nmq (1 ≤ n ≤ 3·1050 ≤ m < n1 ≤ q ≤ 3·105) — the number of cities, the number of the roads we already have and the number of queries, correspondingly.
Each of the following m lines contains two integers, ai and bi (ai ≠ bi; 1 ≤ ai, bi ≤ n). These numbers represent the road between citiesai and bi. There can be at most one road between two cities.
Each of the following q lines contains one of the two events in the following format:
  • 1 xi. It is the request Andrew gives to Dima to find the length of the maximum path in the region that contains city xi (1 ≤ xi ≤ n).
  • 2 xi yi. It is the request Andrew gives to Dima to merge the region that contains city xi and the region that contains city yi(1 ≤ xi, yi ≤ n). Note, that xi can be equal to yi.
    Output
    For each event of the first type print the answer on a separate line.
    Sample test(s)
    input
    6 0 6
    2 1 2
    2 3 4
    2 5 6
    2 3 2
    2 5 3
    1 1
    output
    4

    -----------------------------------------------------EDITORIAL------------------------

    INITIALLY FORM THE GRAPH  FROM THE GIVEN EDGES , NOW APPLY 2 DFS ON EACH DISCONNECTED COMPONENTS , AND SET MAXIM LENGTH FOR EACH DISCONNECTED COMPONENT

    NOW FOR MERGING TWO WEGMENTS SAY a AND b WE ALWAYS TRY TO ADD THESE TWO SEGMENTS FROM CENTER OF BOTH SEGMENTS SO THAT LENGTH OF LONGEST SEGMENT AFTER MERGING WILL NOT INCREASE VERY MUSH ,,
    ----------------------------------------------CODE--------------------------------------------------------------
    #include<iostream>
    #include<bits/stdc++.h>
    #include<stdio.h>
    #include<vector>
    #include<algorithm>
    using namespace std;
    int rank[300100];
    int parent[300100];
    list<int> li[300100];
    int used[300100];


    int fix(int start,int par)
     {
      stack<pair<int,int> > s;
          int max=0;
          int end=-1;
          s.push({start,1});
          used[start]=3;
          while(!s.empty())
           {
            int start=s.top().first;
            rank[start]=0;
            parent[start]=par;
            int lev=s.top().second;
            s.pop();
             if(max<lev)
              {
              max=lev;
              
     }
            list<int>:: iterator it;
            for(it=li[start].begin();it!=li[start].end();it++)
             {
              if(used[*it]==2)
               {
                used[*it]=3;
                s.push({*it,lev+1});
      }
    }
      }
      rank[start]=max;
     }
    int dfs(int start)
     {
          stack<pair<int,int> > s;
          int max=0;
          int end=0;
          s.push({start,1});
          used[start]=2;
          while(!s.empty())
           {
            int start=s.top().first;
            int lev=s.top().second;
            s.pop();
             if(max<lev)
              {
              max=lev;
              end=start;
     }
            list<int>:: iterator it;
            for(it=li[start].begin();it!=li[start].end();it++)
             {
              if(used[*it]==1)
               {
                used[*it]=2;
                s.push({*it,lev+1});
      }
    }
      }
      fix(end,end);
      return 0;
     }
     
     
    int  find(int  a)
      {
        if(parent[a]!=parent[parent[a]])
         {
          parent[a]=find(parent[a]);
         }

         return parent[a];
     }
     
     
    int merge(int a, int  b)
    {
    //cout<<"merge "<<a<<" "<<b<<endl;
      int x=find(a);
      int y=find(b);
      if(rank[x]>=rank[y])
      {
          parent[y]=x;
          if(rank[x]<=2)
           {
            rank[x]+=rank[y];
            rank[y]=0;
      }
      else
      {
      rank[x]=max(rank[x],(rank[x]/2+1)+(rank[y]/2+1));
      rank[y]=0;
      }
      
       //cout<<"x "<<x<<" "<<rank[x]<<" "<<"y "<<y<<" "<<rank[y]<<endl;
          
       
      }
      else
      {
          parent[x]=y;
        if(rank[y]<=2)
           {
            rank[y]+=rank[x];
            rank[x]=0;
      }
      else
      {
      rank[y]=max(rank[y],(rank[y]/2+1)+(rank[x]/2+1));
      rank[x]=0;
      }
          // cout<<"x "<<x<<" "<<rank[x]<<" "<<"y "<<y<<" "<<rank[y]<<endl;
      }
    }




    int main()
    {
     int n;
     cin>>n;
     int m;
     cin>>m;
     int q;
      cin>>q;
      


     
     for(int i=1;i<=n;i++)
     {
        parent[i]=i;
         rank[i]=1;
     }


     for(int i=0;i<m;i++)
     {
              int a,b;
             scanf("%d %d",&a,&b);
               used[a]=1;
               used[b]=1;
               li[a].push_back(b);
               li[b].push_back(a);
     }
     
     
     for(int i=1;i<=n;i++)
      {
      if(used[i]==1)
       {
        dfs(i);
     
    }
      }
      
      
      
     for(int i=0;i<q;i++)
      {
      int t;
       scanf("%d",&t);
       if(t==1)
        {
         int a;
         scanf("%d",&a);
          cout<<rank[find(a)]-1<<endl;
    }
    else
    {
    int a,b;
    scanf("%d %d",&a,&b);
     if(find(a)!=find(b))
      {
        merge(a,b);
    }
    }
      }


     return 0;
    }

    ------------------------------------------------------SMALL CODE------------------------------------
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int MX=300100;
    int n,m,q,x,y,t,best,w,a[MX],p[MX],r[MX];
    vector<int> g[MX];
    int fs(int x) {
      if (x!=p[x]) p[x]=fs(p[x]);
      return p[x];
    }
    void un(int x, int y) {
      if (x==y) return;
      if (r[x]<r[y]) {
        p[x]=y;
        a[y]=max(max(a[x],a[y]),(a[x]+1)/2+(a[y]+1)/2+1);
      } else {
        p[y]=x;
        a[x]=max(max(a[x],a[y]),(a[x]+1)/2+(a[y]+1)/2+1);
        if (r[x]==r[y]) r[x]++;
      }
    }
    void dfs(int i, int prev, int d) {
      p[i]=x;
      if (d>best) { best=d; w=i; }
      for (int j=0; j<g[i].size(); j++) if (g[i][j]!=prev) dfs(g[i][j],i,d+1);
    }
    int main() {
      scanf("%d%d%d",&n,&m,&q);
      while (m--) {
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
      }
      for (x=1; x<=n; x++) if (!p[x]) {
        best=-1; dfs(x,0,0);
        best=-1; dfs(w,0,0);
        a[x]=best;
      }
      while (q--) {
        scanf("%d%d",&t,&x);
        if (t==2) {
          scanf("%d",&y);
          un(fs(x),fs(y));
        } else printf("%d\n",a[fs(x)]);
      }
      return 0;
    }

    Monday, 4 January 2016

    B. Quantity of Strings

    B. Quantity of Strings

    Just in case somebody missed it: this winter is totally cold in Nvodsk! It is so cold that one gets funny thoughts. For example, let's say there are strings with the length exactly n, based on the alphabet of size m. Any its substring with length equal to k is a palindrome. How many such strings exist? Your task is to find their quantity modulo 1000000007 (109 + 7). Be careful and don't miss a string or two!
    Let us remind you that a string is a palindrome if it can be read the same way in either direction, from the left to the right and from the right to the left.
    Input
    The first and only line contains three integers: nm and k (1 ≤ n, m, k ≤ 2000).
    Output
    Print a single integer — the number of strings of the described type modulo 1000000007 (109 + 7).
    Sample test(s)
    input
    1 1 1
    output
    1
    input
    5 2 4
    output
    2
    Note
    In the first sample only one string is valid: "a" (let's denote the only letter of our alphabet as "a").
    In the second sample (if we denote the alphabet letters as "a" and "b") the following strings are valid: "aaaaa" and "bbbbb".
    --------------------------------------------------editorial------------------------------------------------
    We can offer you two solitions:
    1. You can build a graph with positions in sting as a nodes and equality in any substring of length k as edges. Lets denote e the number of components in the graph. The answer is me.
    2. Analyze four cases:
      • k = 1 or ะบ > n, the answer is mn.
      • k = n, the answer is m(n + 1) / 2.
      • k mod 2 = 1, any string like abababab... is ok, so the answer is m2.
      • k mod 2 = 0, all symbols coincide and the answer is m.
      • ------------------------------------------or we can use mst ---------------------------------------
      • #include<iostream>
      • #include<bits/stdc++.h>
      • using namespace std;
      • int rank[20000];
      • int par[20000];
      • int has[20000];
      • int  find(int  a)
      •       {
      •         if(par[a]!=par[par[a]])
      •          {
      •           par[a]=find(par[a]);
      •          }
      •      
      •          return par[a];
      •      }
      •      void add(int a , int b)
      •      {
      •       int x=find(a);
      •       int y=find(b);
      •       if(rank[x]>rank[y])
      •       {
      •        par[y]=x;
      •      }
      •      else
      •      {
      •         par[x]=y;
      •         if(rank[x]==rank[y])
      •         {
      •           rank[y]++;
      •     }
      •      }
      •      }

      • int main()
      •  {
      •   int n,m,kk;
      •   cin>>n>>m>>kk;
      •   for(int i=1;i<=n;i++)
      •   {
      •   par[i]=i;
      •   rank[i]=0;
      • }
      •   for(int i=1;i<=n-kk+1;i++)
      •   {
      •   int j=i,k=i+kk-1;
      •     while(j<k)
      •      {
      •     
      •       if(find(j)!=find(k))
      •        {
      •          // cout<<"add "<<j<<" "<<k<<endl;
      •         add(j,k);
      • }
      • j++;
      • k--;
      •  }
      •   // 7 4 20

      •  }
      •   int ans=0;
      •   for(int i=1;i<=n;i++)
      •    {
      •     if(has[find(i)]==0)
      •     {
      •     has[find(i)]=1;
      •     ans++;
      • }
      • }
      • ///cout<<ans<<endl;
      • long long int fin=1;
      • long long int mod=1000000007;
      • // for(int i=1;i<=n;i++) cout<<par[i]<<" ";
      • // cout<<endl;
      • for(int i=1;i<=ans;i++)
      • {
      • fin=(fin*m) %mod;
      • }
      • cout<<fin<<endl;
      • //else cout<<"0"<<endl;
      •  }