Thursday 12 December 2013

Check if graph is semiconnected

22.5-7
A directed graph G=(V,E) is semiconnected if, for all pairs of vertices (u,v)
we have u to v or v to u. Give an efficient algorithm to determine whether
or not G is semiconnected. Prove that your algorithm is correct, and analyze its
running time.


Call STRONGLY-CONNECTED-COMPONENTS.

Form the component graph.

Topologically sort the component graph. It is possible to topologically sort the component graph, because component graph is always a DAG (Directed Acyclic Graph)


 Verify that the sequence of vertices (v1,v2,...vk) given by topological sort forms a linear chain in the component graph. That is, verify that the edges (v1,v2),(v2,v3) ,(v (k-1),vk)  exist in the component graph. If the vertices form a linear chain, then the original graph is semiconnected; otherwise it is not.

Because we know that all vertices in each SCC are mutually reachable from each other, it suffices to show that the component graph is semiconnected if and only if it contains a linear chain.
Total running time is O(V+E).

Check if graph is singly connected

A directed graph G = (V,E) is singly connected if there is at most one
directed path from u to v for all vertices u, v  in V . Give an efficient algorithm to determine whether or not a directed graph is singly connected.

Solution. For each vertex u in V , perform a DFS on the given graph G. Check if there are any foward edges or cross edges (in the same component) in any one of the searches. If no such edges exist, then the graph is singly connected, else not.
Time complexity: O(|V |(|V | + |E|)).
The graph is singly connected even with back edges existed. Since back edges implies there is a path u to  v and v to u, which is consistent with the definition of single connectedness.


DFS using stack not recursion.

s[x] = start time of x;
f[x]= finish time of x
color[x] - stores the state of the vertex
WHITE: undiscovered
GRAY: still processing
BLACK: finished
time - global variable to update start and finish times

 DFS(G)
         for each u in V do
                  color[u]=WHITE;
                  p[u]=NIL;
         end for
         for each u in V do
                  if color[u]=WHITE do
                         DFS-VISIT(G,u)
                  end if
         end for

DFS-VISIT(G,u)
         stack S=nil
         push(S,u)
         while S is not empty do
                   x=pop(S)
                  if color[x]=WHITE do
                            time=time+1
                            s[x]=time
                            color[x]=GRAY
                            push(S,x)
                            for each v in Adj[x] do
                                     if color[v]=WHITE do
                                              p[v]=x;
                                              push(S,v);                                             
                                    end if
                           end for
                  else if colox[x]=GRAY do
                           time=time+1
                            f[x]=time
                            color[x]=BLACK
                   end if
          end while

Check if a graph is bipartite/ determines whether it is possible to designate some of the wrestlers as good guys and the remainder as bad guys such that each rivalry is between a good guy and a bad guy.

Algorithm:
Perform as many BFS's as needed to cover all vertices. Assign all wrestlers whose distance is even as good guys and all wrestlers whose distance is odd to be bad guys.Then check each edge to verify that it goes from a good guy to a bad guy. 

O(V+E) : BFS using adjacency lists
O(V): designate a wrestler as good or bad
0(E): check edges.



Simpler implementation : Uses adjacency matrix.


// C++ program to find out whether a given graph is Bipartite or not
#include <iostream>
#include <queue>
#define V 4
using namespace std;
// This function returns true if graph G[V][V] is Bipartite, else false
bool isBipartite(int G[][V], int src)
{
    // Create a color array to store colors assigned to all veritces. Vertex
    // number is used as index in this array. The value '-1' of  colorArr[i]
    // is used to indicate that no color is assigned to vertex 'i'.  The value
    // 1 is used to indicate first color is assigned and value 0 indicates
    // second color is assigned.
    int colorArr[V];
    for (int i = 0; i < V; ++i)
        colorArr[i] = -1;
    // Assign first color to source
    colorArr[src] = 1;
    // Create a queue (FIFO) of vertex numbers and enqueue source vertex
    // for BFS traversal
    queue <int> q;
    q.push(src);
    // Run while there are vertices in queue (Similar to BFS)
    while (!q.empty())
    {
        // Dequeue a vertex from queue ( Refer http://goo.gl/35oz8 )
        int u = q.front();
        q.pop();
         // Find all non-colored adjacent vertices
        for (int v = 0; v < V; ++v)
        {
            // An edge from u to v exists and destination v is not colored
            if (G[u][v] && colorArr[v] == -1)
            {
                // Assign alternate color to this adjacent v of u
                colorArr[v] = 1 - colorArr[u];
                q.push(v);
            }
            //  An edge from u to v exists and destination v is colored with
            // same color as u
            else if (G[u][v] && colorArr[v] == colorArr[u])
                return false;
        }
    }
    // If we reach here, then all adjacent vertices can be colored with
    // alternate color
    return true;
}
// Driver program to test above function
int main()
{
    int G[][V] = {{0, 1, 0, 1},
        {1, 0, 1, 0},
        {0, 1, 0, 1},
        {1, 0, 1, 0}
    };
    isBipartite(G, 0) ? cout << "Yes" : cout << "No";
    return 0;
}
Time complexity: O(V^2) (BFS with adjacency matrix)
Better : O(V+E): BFS with adjacency list

Tuesday 10 December 2013

Show that determining whether a directed graph G contains a universal sink – a vertex of indegree |V| - 1 and outdegree 0 – can be determined in time O(V ).

How many sinks could a graph have?
  • 0 or 1
How can we determine whether a given vertex u is a universal sink?
  • The u row must contain 0’s only
  • The u column must contain 1’s only
  • A[u][u]=0
How long would it take to determine whether a given vertex u is a universal sink?
  • O(V) time 
UNIVERSAL-SINK(A)
let A be |V|x|V|
i=j=1
while i<=|V| and j<=|V| 
      if aij =1
          then i=i+1;
          else j=j+1;
if i>|V|
   return "no universal sink";
if ISSINK(A,i) =false
   return "no universal sink";
else 
  return i;

ISSINK(A,k)
let A be |V|x|V|
for j=1 to |V|
   if akj=1 or (ajk=0 and j!=k)
       return false
return true  




Tuesday 22 October 2013

Matrix exponentiation

The Tribonacci Numbers:

F(n) = F(n-1) + F(n-2) + F(n-3),  F(1) = 1; F(2) = 1; F(3) = 2
 

* for N as large as 10^15, using dp will always be very slow, regardless of the time limit. 

*The basic idea behind matrix exponentiation,  is to use the base cases of the recurrence relationship in order to assemble a matrix which will allow us to compute values fast.

On our case we have:
F(1) = 1
F(2) = 1
F(3) = 2
And we now have a relationship that will go like this:
|f(4)|    = MATRIX * |f(1)|
|f(3)|               |f(2)|
|f(2)|               |f(3)|
Now all that is left is to assemble the matrix... and that is done based both on the rules of matrix multiplication and on the recursive relationship... Now, on our example we see that to obtain f(4), the 1st line of the matrix needs to be composed only of ones, as f(4) = 1 f(3) + 1 f(2) + 1* f(1).
Now, denoting the unknown elements as *, we have:
|f(4)|   = |1 1 1| * |f(1)|
|f(3)|     |* * *|   |f(2)|
|f(2)|     |* * *|   |f(3)|
For the second line, we want to obtain f(3), and the only possible way of doing it is by having:
  |f(4)|   = |1 1 1| * |f(1)|
  |f(3)|     |0 0 1|   |f(2)|
  |f(2)|     |* * *|   |f(3)|
To get the value of f(2), we can follow the same logic and get the final matrix:
|1 1 1|
|0 0 1|
|0 1 0|
To end it, we now need to generalize it, and, as we have 3 base cases, all we need to do to compute the Nth tribonacci number in O(logN) time, is to raise the matrix to the power N -3 to get:

|f(n)|   =   |1 1 1|^(N-3) * |f(1)|
|f(n-1)|     |0 0 1|         |f(2)|
|f(n-2)|     |0 1 0|         |f(3)|

The power of the matrix can now be computed in O(logN) time using repeated squaring applied to matrices and the method is complete... Below is the Python code that does this, computing the number modulo 10000000007.


def matrix_mult(A, B):
  C = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
  for i in range(3):
    for j in range(3):
      for k in range(3):
        C[i][k] = (C[i][k] + A[i][j] * B[j][k]) % 1000000007
  return C

def fast_exponentiation(A, n):
  if n == 1:
    return A
  else:
    if n % 2 == 0:
      A1 = fast_exponentiation(A, n/2)
      return matrix_mult(A1, A1)
    else:
      return matrix_mult(A, fast_exponentiation(A, n - 1))

def solve(n):
    A = [[1,1,1],[0,0,1],[0,1,0]]
    A_n = fast_exponentiation(A,n-3)
    return A_n[0][0] + A_n[0][1] + A_n[0][2]*2




OTHER LINKS:
http://discuss.codechef.com/questions/2263/crowd-editorial

Sunday 1 September 2013

Median of medians

Median of Medians Algorithm

Quickselect is linear-time on average, but it can require quadratic time with poor pivot choices. This is because quickselect is a decrease and conquer algorithm, with each step taking O(n) time in the size of the remaining search set. If the search set decreases exponentially quickly in size (by a fixed proportion), this yields a geometric series times the O(n) factor of a single step, and thus linear overall time. However, if the search set decreases slowly in size, such as linearly (by a fixed number of elements, in the worst case only reducing by one element each time), then a linear sum of linear steps yields quadratic overall time. For example, the worst case occurs when pivoting on the smallest element at each step, such as applying quickselect for the maximum element to already sorted data and taking the first element as pivot each time.

If one instead consistently chooses "good" pivots, this is avoided and one always gets linear performance even in the worst case. A "good" pivot is one for which we can establish that a constant proportion of elements fall both below and above it, as then the search set decreases at least by a constant proportion at each step, hence exponentially quickly, and the overall time remains linear. The median is a good pivot – the best for sorting, and the best overall choice for selection – decreasing the search set by half at each step. Thus if one can compute the median in linear time, this only adds linear time to each step, and thus the overall complexity of the algorithm remains linear.

The median-of-medians algorithm does not actually compute the exact median, but computes an approximate median, namely a point that is guaranteed to be between the 30th and 70th percentiles . Thus the search set decreases by a fixed proportion at each step, namely at least 30% (so at most 70% left). Lastly, the overhead of computing the pivot consists of recursing in a set of size 20% the size of the original search set, plus a linear factor, so at linear cost at each step, the problem is reduced to 90% (20% and 70%) the original size, which is a fixed proportion smaller, and thus by induction the overall complexity is linear in size.


Median-of-medians algorithm:
  • Line up elements in groups of five (this number 5 is not important, it could be e.g. 7 without changing the algorithm much). Call each group S[i], with i ranging from 1 to n/5.
  • Find the median of each group. (Call this x[i]). This takes 6 comparisons per group, so 6n/5 total (it is linear time because we are taking medians of very small subsets).
  • Find the median of the x[i], using a recursive call to the algorithm. If we write a recurrence in which T(n) is the time to run the algorithm on a list of n items, this step takes time T(n/5). Let M be this median of medians.
  • Use M to partition the input and call the algorithm recursively on one of the partitions, just like in quickselect.
The chosen pivot is both less than and greater than half of the elements in the list of medians, which is around n/10 elements (½×n/5) for each half. Each of these elements is a median of 5, making it less than 2 other elements and greater than 2 other elements outside the block. Hence, the pivot is less than 3(n/10) elements outside the block, and greater than another 3(n/10) elements inside the block. Thus the chosen median splits the elements somewhere between 30%/70% and 70%/30%, which assures worst-case linear behavior of the algorithm. To visualize:
One iteration on the list {0,1,2,3,...99}

12
15
11
2
9
5
0
7
3
21
44
40
1
18
20
32
19
35
37
39

13
16
14
8
10
26
6
33
4
27
49
46
52
25
51
34
43
56
72
79
Medians 17
23
24
28
29
30
31
36
42
47
50
55
58
60
63
65
66
67
81
83

22
45
38
53
61
41
62
82
54
48
59
57
71
78
64
80
70
76
85
87

96
95
94
86
89
69
68
97
73
92
74
88
99
84
75
90
77
93
98
91
(red = "(one of the two possible) median of medians", gray = "number < red", white = "number > red")

Proof of O(n) running time

The median-calculating recursive call does not exceed worst-case linear behavior because the list of medians is 20% of the size of the list, while the other recursive call recurses on at most 70% of the list, making the running time
T(n) \leq T(n \cdot 2/10) + T(n \cdot 7/10) + c \cdot n.
The O(n) term c n is for the partitioning work (we visited each element a constant number of times, in order to form them into n/5 groups and take each median in O(1) time).
From this, using induction – or summing the geometric series, obtaining 1/(1-9/10) = 1/(1/10) = 10 for overall scaling factor – one can easily show that
T(n) \leq 10 \cdot c \cdot n \in O(n).

Code
// selects the median of medians in an array
int select(int *a, int s, int e, int k){
    // if the partition length is less than or equal to 5
    // we can sort and find the kth element of it
    // this way we can find the median of n/5 partitions
    if(e-s+1 <= 5){
        sort(a+s, a+e);
        return s+k-1;
    }
    
    // if array is bigger 
    // we partition the array in subarrays of size 5
    // no. of partitions = n/5 = (e+1)/5
    // iterate through each partition
    // and recursively calculate the median of all of them
    // and keep putting the medians in the starting of the array
    for(int i=0; i<(e+1)/5; i++){
        int left = 5*i;
        int right = left + 4;
        if(right > e) right = e;
        int median = select(a, 5*i, 5*i+4, 3);
        swap(a[median], a[i]);
    }
    
    // now we have array 
    // a[0] = median of 1st 5 sized partition
    // a[1] = median of 2nd 5 sized partition
    // and so on till n/5
    // to find out the median of these n/5 medians
    // we need to select the n/10th element of this set (i.e. middle of it)
    return select(a, 0, (e+1)/5, (e+1)/10);
}

int main(){
    int a[] = {6,7,8,1,2,3,4,5,9,10};
    int n = 10;
    
    int mom = select(a, 0, n-1, n/2);
    cout<<"Median of Medians: " << a[mom] << endl;
    return 0;
}

Saturday 3 August 2013

lab exam ds

The square field consists of M ∗ M cells. Each cell is colored in one of three colors (1,2,3). The initial state
is chosen in one of the cells of color 1. In each step one allowed to move one cell up, down, left or right
remaining inside the field.
You are to define the minimal amount of steps one should make to get a cell of color 3 independent on the
initial state. NOTE: this means you could be starting at any of the 1.
Also note that the field contains at least one cell of color 1 and at least one cell of color 3.
1.1
Input Format
The input consists of several input blocks. The first line of each block contains integer M, the size of the
field. Then there are M lines with colors of the cells.
1.2
Output Format
For each input block the output should consist of one line with the integer, the minimal amount of steps one
should make to get a cell of color 3 independent on the initial state.
1.3
Sample Input
4
1223
2123
2213
3212
2
12
33
1.4
Sample Output
3
1


Program:


#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
typedef struct node
{
    int n;
    char v;
    struct node*next;
}node;
int main(void)
{
    char val[10005];
    int t,i,m,j,k,in[10005];
    node* a[10005],*tmp;
    char d,c='a';
    m=0;
    while((c=getchar())!=EOF)//scan char by char till EOF
    {
    while(c>='0'&&c<='9')//find m
    {
        m=m*10+c-'0';
        c=getchar();
    }
    k=0;
    for(i=0;i<m*m;i++)//scan the matrix
    {
        scanf("%c",&val[i]);//store the values in val array
        a[i]=NULL;//set ith node to NULL
        if(val[i]=='1')//store indices of all 1's in in array
        in[k++]=i;
        if(((i+1)%m)==0)//scan \n
        d=getchar();
    }
    c=d;
    for(i=0;i<m*m;i++)// create linked lists for adjacency list representation of matrix as a graph
    {
        if(i%m!=0)
        {
        tmp=a[i];
        a[i]=malloc(sizeof(node));
        a[i]->n=i-1;
        a[i]->v=val[i-1];
        a[i]->next=tmp;
        }
        if(i+1<m*m&&(i+1)%m!=0)
        {
        tmp=a[i];
        a[i]=malloc(sizeof(node));
        a[i]->n=i+1;
        a[i]->v=val[i+1];
        a[i]->next=tmp;
        }
        if(i-m>=0)
        {
        tmp=a[i];
        a[i]=malloc(sizeof(node));
        a[i]->n=i-m;
        a[i]->v=val[i-m];
        a[i]->next=tmp;
        }
        if(i+m<m*m)
        {
        tmp=a[i];
        a[i]=malloc(sizeof(node));
        a[i]->n=i+m;
        a[i]->v=val[i+m];
        a[i]->next=tmp;
        }
    }
      int min=0;
    for(i=0;i<k;i++)//find minimum distance b/w each '1' and a '3' and find the maximum of these minimum distances
    {
        int d[10005],flag;
        for(j=0;j<m*m;j++)
        d[j]=INT_MAX;
        int f=0,r=0,vis[10005]={0},queue[10005];
        queue[r++]=in[i];
        d[in[i]]=0;
        vis[in[i]]=1;
        flag=0;
        while(flag==0&&f!=r)
        {
        t=queue[f++];
        for(tmp=a[t];tmp!=NULL;tmp=tmp->next)
        {
            vis[tmp->n]=1;
            d[tmp->n]=d[t]+1;
            queue[r++]=tmp->n;
            if(tmp->v=='3')
            {
            flag=1;
            if(d[tmp->n]>min)
                min=d[tmp->n];
            }
        }
        }
    }
    printf("%d\n",min);
    m=0;
    }
    return 0;
}


Thursday 1 August 2013

12376 - As Long as I Learn, I Live Time limit: 3.000 seconds

http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=3798

What makes problem solving so interesting? What makes it challenging? Why we put so much effort on it but never get bored? For us (problem-setters), it's like 'As long as I learn, I live!' We learn so many beautiful things, we find great ideas and techniques and there is no end to it.

In this problem, you are given a person's life stages in graph form. There are n nodes in the graph. Nodes represent stages, numbered from 0 to n-1, and edges represents that he can move from one stage to another. 0th node is the node where he starts his journey. You may have guessed; there will be no cycles in the graph (no one can back to past!).
In each node, a value x is attached, it means he will learn x units, if he comes into this node. For example, the graph in the picture represents a person's life stages. The circles present nodes, the value in a circle represents that it will be gained if the person comes into this node. The numbers in rectangular boxes represents the node ids. If the person reaches the 1st node he will learn 8 added units, if he reaches 4th node, he will learn 7 added units.

As in real life, no one knows the future, but can predict some common things in near future. If the person is in node u, he only knows the nodes that have an edge from u. The person wants to learn more, that's why, he always takes the stage that looks better, i.e. has maximum value. So, if he is in node 0, he only knows the learning units in node 1 and 2, but doesn't know about nodes 3, 4, or 5. He will prefer node 2 over node 1 (because node 2 will give him 9 learning units). He continues journey in this method. He can finish at any stage, but will try to learn more. You can assume that the graph is given such that from any node, the next node can be picked deterministically i.e. from any node u, there will be exactly one node v which has the maximum value and there is an edge from u to v.

Input
Input starts with an integer T (≤ 100), denoting the number of test cases.

Each case starts with a blank line. Next line contains two integers n (2 ≤ n ≤ 100) and m (n-1 ≤ m ≤ n*(n-1)/2), n denotes the number of nodes in the graph and m denotes the number of edges in the graph. The next line contains n space separated integers denoting the learning units in the nodes respectively. The values will be between 1 and 1000 (inclusive) except the 0th node will have a value 0. Each of the next m lines contains two integers u v (0 ≤ u, v < n, u ≠ v) meaning that there is a directed edge from u to v. You can safely assume that the given graph will follow the restrictions described above. And from 0th node, it can be possible to go to any node. There will be at most one edge between any pair of nodes.

Output

For each case, print the case number and the maximum total learning units the person can gain (following the strategy mentioned above) and the node id where the person ends journey.
 Algorithm:
 Graph BFS or DFS problem

This problem you can solve using recursive method, or you can use BFS or DFS for solve this problem.

The recursive method is best solution for solve this problem.

This method is

store all learning unit to LU[100]
total_learning_unit=LU[0];
run findAns(0);

void findAns(int u)
----if u has no adjacency node then set ans_node=u and return //i.e. break find ans
----find the max learning unit from all node which are adjacency of u. suppose the max learning unit node is v.
----total_learning_unit += LU[v];
----findAns(v);

print total_learning_unit and ans_node

Program:
#include<stdio.h>
struct list
{
    int b[100];
    int k;
};
int main()
{
    struct list a[105];
    int j,f,s,o,l,i,u,v,c[105],t,n,m,z;
    scanf("%d",&t);
    char d;
    for(o=1;o<=t;o++)
    {
    scanf("%c%d%d",&d,&n,&m);
    for(i=0;i<n;i++)
    {
        a[i].k=0;
        scanf("%d",&c[i]);
    }
    for(i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        a[u].b[a[u].k++]=v;
    }
    s=0;
    l=0;
    while(1)
    {
        m=0;
        if(a[s].k==0)
        break;
        for(i=0;i<a[s].k;i++)
        {
        if(c[a[s].b[i]]>m)
        {
            m=c[a[s].b[i]];
            z=a[s].b[i];
        }
        }
        l+=m;
        s=z;
    }
    printf("Case %d: %d %d\n",o,l,s);
    }
    return 0;
}


 
Sample Input                              Output for Sample Input
1

6 6
0 8 9 2 7 5
5 4
5 3
1 5
0 1
0 2
2 1
Case 1: 29 4







Tuesday 30 July 2013

Domino Principle

http://codeforces.com/problemset/problem/56/E

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Vasya is interested in arranging dominoes. He is fed up with common dominoes and he uses the dominoes of different heights. He put n dominoes on the table along one axis, going from left to right. Every domino stands perpendicular to that axis so that the axis passes through the center of its base. The i-th domino has the coordinate xi and the height hi. Now Vasya wants to learn for every domino, how many dominoes will fall if he pushes it to the right. Help him do that.
Consider that a domino falls if it is touched strictly above the base. In other words, the fall of the domino with the initial coordinate x and height h leads to the fall of all dominoes on the segment [x + 1, x + h - 1].
Input
The first line contains integer n (1 ≤ n ≤ 105) which is the number of dominoes. Then follow n lines containing two integers xi and hi ( - 108 ≤ xi ≤ 108, 2 ≤ hi ≤ 108) each, which are the coordinate and height of every domino. No two dominoes stand on one point.
Output
Print n space-separated numbers zi — the number of dominoes that will fall if Vasya pushes the i-th domino to the right (including the domino itself).
Sample test(s)
Input
4
16 5
20 5
10 10
18 2
Output
3 1 4 1 
Input
4
0 10
1 5
9 10
15 10
Output
4 1 2 1 
 
Code:
 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100010;
struct node{
    int x,y,p;
}a[maxn];
int n;
int f[maxn],ans[maxn];
bool cmp(node i,node j)
{
    return i.x<j.x;
}
int main()
{
    int i,x,y;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
    scanf("%d%d",&x,&y);
    a[i].x=x;a[i].y=x+y-1;
    a[i].p=i;
    }
    sort(a+1,a+n+1,cmp);
    for(i=n;i>=1;i--){
    f[i]=1;
    for(int j=i+1;j<=n;j+=f[j]){
        if (a[i].y>=a[j].x) f[i]+=f[j];
        else break;
    }
    ans[a[i].p]=f[i];
    }
    for(i=1;i<=n;i++) printf("%d ",ans[i]);
    printf("\n");
    return 0;
}

Corporation Mail

http://codeforces.com/problemset/problem/56/C

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
The Beroil corporation structure is hierarchical, that is it can be represented as a tree. Let's examine the presentation of this structure as follows:
  • employee ::= name. | name:employee1,employee2, ... ,employeek.
  • name ::= name of an employee
That is, the description of each employee consists of his name, a colon (:), the descriptions of all his subordinates separated by commas, and, finally, a dot. If an employee has no subordinates, then the colon is not present in his description.
For example, line MIKE:MAX.,ARTEM:MIKE..,DMITRY:DMITRY.,DMITRY... is the correct way of recording the structure of a corporation where the director MIKE has subordinates MAX, ARTEM and DMITRY. ARTEM has a subordinate whose name is MIKE, just as the name of his boss and two subordinates of DMITRY are called DMITRY, just like himself.
In the Beroil corporation every employee can only correspond with his subordinates, at that the subordinates are not necessarily direct. Let's call an uncomfortable situation the situation when a person whose name is s writes a letter to another person whose name is also s. In the example given above are two such pairs: a pair involving MIKE, and two pairs for DMITRY (a pair for each of his subordinates).
Your task is by the given structure of the corporation to find the number of uncomfortable pairs in it.
Input
The first and single line contains the corporation structure which is a string of length from 1 to 1000 characters. It is guaranteed that the description is correct. Every name is a string consisting of capital Latin letters from 1 to 10 symbols in length.
Output
Print a single number — the number of uncomfortable situations in the company.
Sample test(s)
Input
MIKE:MAX.,ARTEM:MIKE..,DMITRY:DMITRY.,DMITRY...
Output
3
Input
A:A..
Output
1
Input
A:C:C:C:C.....
Output
6

Code:
#include<iostream>
using namespace std;
    char a;
    int n,res;
    string s[1001];
int main()
{
    while(cin>>a)
    {
 if(a=='.')
 {
     for(int i=0;i<n;i++)
  if(s[i]==s[n])
      res=res+1;
     s[n]="";
     n--;
 }
 else
 {
     if(a==':')
  n=n+1;
     else
     {
  if(a==',')
      n++;
  else
      s[n]+=a;
     }
 }
    }
    cout<<res<<endl;
    return 0;
} 
 

Spoilt Permutation

http://codeforces.com/problemset/problem/56/B

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Vasya collects coins: he has exactly one coin for every year from 1 to n. Naturally, Vasya keeps all the coins in his collection in the order in which they were released. Once Vasya's younger brother made a change — he took all the coins whose release year dated from l to r inclusively and put them in the reverse order. That is, he took a certain segment [l, r] and reversed it. At that the segment's endpoints did not coincide. For example, if n = 8, then initially Vasya's coins were kept in the order 1 2 3 4 5 6 7 8. If Vasya's younger brother chose the segment [2, 6], then after the reversal the coin order will change to 1 6 5 4 3 2 7 8. Vasya suspects that someone else could have spoilt the permutation after his brother. Help him to find that out. Check if the given permutation can be obtained from the permutation 1 2 ... n using exactly one segment reversal. If it is possible, find the segment itself.
Input
The first line contains an integer n (1 ≤ n ≤ 1000) which is the number of coins in Vasya's collection. The second line contains space-separated n integers which are the spoilt sequence of coins. It is guaranteed that the given sequence is a permutation, i.e. it contains only integers from 1 to n, and every number is used exactly 1 time.
Output
If it is impossible to obtain the given permutation from the original one in exactly one action, print 0 0. Otherwise, print two numbers l r (1 ≤ l < r ≤ n) which are the endpoints of the segment that needs to be reversed to obtain from permutation 1 2 ... n the given one.
Sample test(s)
Input
8
1 6 5 4 3 2 7 8
Output
2 6
Input
4
2 3 4 1
Output
0 0
Input
4
1 2 3 4
Output
0 0
 
Code:
 #include<iostream>
using namespace std;
int main()
{
    int x,y,n,a[1001];
    cin>>n;
    for(int i=0;i<n;i++)
    {
 cin>>a[i];
    }
    x=0;
    y=n-1;
    while(a[x]==x+1)
    {
 x++;
    }
    while(a[y]==y+1)
    {
 y--;
    }
    if(x>y)
    {
 cout<<"0 0\n";
    }
    else
    {
 for(int i=x;i<=y;i++)
 {
     if(a[i]!=y+x+1-i)
     {
  cout<<"0 0\n";
  return 0;
     }
 }
 cout<<x+1<<" "<<y+1<<endl;
    }
    return 0;
}

A. Bar

memory limit per test
256 megabytes
input
standard input
output
standard output
According to Berland laws it is only allowed to sell alcohol to people not younger than 18 years. Vasya's job is to monitor the law's enforcement. Tonight he entered a bar and saw n people sitting there. For every one of them Vasya happened to determine either the age or the drink the person is having. Vasya can check any person, i.e. learn his age and the drink he is having at the same time. What minimal number of people should Vasya check additionally to make sure that there are no clients under 18 having alcohol drinks?
The list of all alcohol drinks in Berland is: ABSINTH, BEER, BRANDY, CHAMPAGNE, GIN, RUM, SAKE, TEQUILA, VODKA, WHISKEY, WINE
Input
The first line contains an integer n (1 ≤ n ≤ 100) which is the number of the bar's clients. Then follow n lines, each describing one visitor. A line either contains his age (an integer from 0 to 1000) or his drink (a string of capital Latin letters from 1 to 100 in length). It is guaranteed that the input data does not contain spaces and other unnecessary separators.
Only the drinks from the list given above should be considered alcohol.
Output
Print a single number which is the number of people Vasya should check to guarantee the law enforcement.
Sample test(s)
Input
5
18
VODKA
COKE
19
17
Output
2
Note
In the sample test the second and fifth clients should be checked.

Code:
a=["ABSINTH", "BEER", "BRANDY", "CHAMPAGNE", "GIN", "RUM", "SAKE", "TEQUILA", "VODKA", "WHISKEY", "WINE"]
x=input()
n=0
for i in range(x):
    y=raw_input()
    if y in a:
    n=n+1
    else:
    j=0;
    for i in y:
        if (i<'0'or i>'9'):
        j=1
    if j==0:
        if(int(y)<18):
        n=n+1
print n

 

Tuesday 16 July 2013

The Probability Of Winning

Refer:
http://www.codechef.com/problems/PROB

Proof:
assumption:p(t1,t2,t3)=t1/(t1+t2)
There are two parts to the proof .
1. Coins of type 3 don't matter .
2. Initial draw doesn't matter .

You can prove both the claims by mathematical induction
Proof 1 :
p(t1,t2,t3) = t1/(t1+t2+t3) + t3 / ( t1+t2+t3) * p(t1,t2,t3-1) . ( Statement 1 )
By induction hypothesis ,
p(t1,t2,t3-1) = t1/(t1+t2) .
which proves Statement 1 gives us assumed formula

Proof 2 :
p(t1,t2,t3,t4) = t1/(t1+t2+t3) * p(t1-1,t2,t3,t4-1) + t2/(t1+t2+t3) * p(t1,t2-1,t3,t4-1) + t3/(t1+t2+t3) * p(t1,t2,t3-1,t4-1) . (statement 2)
By induction hypothesis ,
p(t1-1,t2,t3,t4-1) = (t1-1)/(t1-1+t2)
p(t1,t2-1,t3,t4-1) = (t1)/(t1+t2-1)
p(t1,t2,t3-1,t4-1) = (t1)/(t1+t2)
which proves statement 2 gives us assumed formula.

alternative solution:
the logic is split in two parts:
  1. t4 has no significance : Note that these tickets are removed randomly, so in some cases the prob of winning will increase and in others it will decrease. Overall, it will have no effect. I was satisfied with this intuition.
  2. t3 has no significance : I actually worked this out mathematically. Let r denote the total number of tickets then we can get,
    P[win] = (t1/r)(1 + t3/(r-1) + t3 (t3-1)/((r-1)(r-2)) + ...
    P[loss] = (t2/r)(1 + t3/(r-1) + t3 (t3-1)/((r-1)(r-2)) + ...
Note that the big multiplicative term is same in both and can be replaced by L.
Also P[win] + P[loss] = 1
So, we have
P[win] + P[loss] = (t1/r + t2/r) * L
1 = (t1/r + t2/r) * L
L = r/(t1 + t2)
We can substitute this value of L back in P[win],
P[win] = (t1/r)* (r/(t1+t2))
P[win] = t1 / (t1+t2)

Program:
#include<stdio.h>
#include<math.h>

int main(){
    long long t,a,b,c,d;
 double ans;
 scanf("%lld",&t);
 while(t--){
  scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
  ans = a/(double)(a+b);
  ans = round(ans*10000000)/10000000;
  printf("%0.7f\n",ans);
 }
 return 0;
}


 

Monday 15 July 2013

Chef and Walking on the rectangle

 
Solution:
/*Chef and Walking on the rectangle*/
#include<stdio.h>
int main()
{
    int K,M,N,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d",&N,&M,&K);
        if(((N==1) && (M<=2)) || ((N<=2) && (M==1)))
            printf("0\n");
        else if((N==1) || (M==1))
            printf("%d\n",K);
        else
            printf("%d\n",(K/2)+(K&1));
    }
    return 0;
}

Thursday 11 July 2013

How to check if a given point lies inside or outside a polygon?

Given a polygon and a point ‘p’, find if ‘p’ lies inside the polygon or not. The points lying on the border are considered inside.
polygon21

Following is a simple idea to check whether a point is inside or outside.
1)Draw a horizontal line to the right of each point and extend it to infinity.
2) Count the number of times a line intersects the polygon. We have:
    even number ---> point is outside
    odd number ----> point is inside
polygon3

If point is same as one of the vertices of polygon, then it intersects with two lines.  We explicitly handle it by comparing the point with n vertices of the polygon.

Following is C++ implementation of the above idea.
// A C++ program to check if a given point lies inside a given polygon
#include <iostream>
#include <limits.h>
using namespace std;
struct Point
{
int x;
int y;
};
// Given three colinear points p, q, r, the function checks if
// point q lies on line segment 'pr'
bool onSegment(Point p, Point q, Point r)
{
if (q.x <= max(p.x, r.x) && q.x >= min(p.x, r.x) &&
q.y <= max(p.y, r.y) && q.y >= min(p.y, r.y))
return true;
return false;
}
// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are colinear
// 1 --> Clockwise
// 2 --> Counterclockwise
int orientation(Point p, Point q, Point r)
{
int val = (q.y - p.y) * (r.x - q.x) -
(q.x - p.x) * (r.y - q.y);
if (val == 0) return 0; // colinear
return (val > 0)? 1: 2; // clock or counterclock wise
}
// The function that returns true if line segment 'p1q1'
// and 'p2q2' intersect.
bool doIntersect(Point p1, Point q1, Point p2, Point q2)
{
// Find the four orientations needed for general and
// special cases
int o1 = orientation(p1, q1, p2);
int o2 = orientation(p1, q1, q2);
int o3 = orientation(p2, q2, p1);
int o4 = orientation(p2, q2, q1);
// General case
if (o1 != o2 && o3 != o4)
return true;
// Special Cases
// p1, q1 and p2 are colinear and p2 lies on segment p1q1
if (o1 == 0 && onSegment(p1, p2, q1)) return true;
// p1, q1 and p2 are colinear and q2 lies on segment p1q1
if (o2 == 0 && onSegment(p1, q2, q1)) return true;
// p2, q2 and p1 are colinear and p1 lies on segment p2q2
if (o3 == 0 && onSegment(p2, p1, q2)) return true;
// p2, q2 and q1 are colinear and q1 lies on segment p2q2
if (o4 == 0 && onSegment(p2, q1, q2)) return true;
return false; // Doesn't fall in any of the above cases
}
// Returns true if the point p lies inside the polygon[] with n vertices
bool isInside(Point polygon[], int n, Point p)
{
// There must be at least 3 vertices in polygon[]
if (n < 3) return false;
// Create a point for line segment from p to infinite
Point extreme = {INT_MAX, p.y};
// Count intersections of the above line with sides of polygon
int count = 0;
for (int i = 0; i < n-1; i++)
{
// If p is same as one of the vertices
if (p.x == polygon[i].x && p.y == polygon[i].y)
return true;
// Otherwise check for intersection
if (doIntersect(polygon[i], polygon[i+1], p, extreme))
count++;
}
// If p is same as last vertex
if (p.x == polygon[n-1].x && p.y == polygon[n-1].y)
return true;
// Last side (from last to first point) is missed in the
// above loop, consider it now
if (doIntersect(polygon[n-1], polygon[0], p, extreme))
count++;
// Return true if count is odd, false otherwise
return count&1; // Same as (count%2 == 1)
}
// Driver program to test above functions
int main()
{
Point polygon[] = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};
int n = sizeof(polygon)/sizeof(polygon[0]);
Point p = {20, 20};
isInside(polygon, n, p)? cout << "Yes \n": cout << "No \n";
p = {5, 5};
isInside(polygon, n, p)? cout << "Yes \n": cout << "No \n";
return 0;
}
Output:
No
Yes
Time Complexity: O(n) where n is the number of vertices in the given polygon.
Source:
http://www.dcs.gla.ac.uk/~pat/52233/slides/Geometry1x1.pdf