176

(6 ответов, оставленных в Offtopic)

Хм... неужели ace.delos.com/JAN08?

177

(2 ответов, оставленных в Problems)

Ну тут надо перебрать 2 вида конечного распределения (111222333 и 333222111). Например, пробуем сделать первый. Сделаем динамику по номеру коровы и типу последней коровы. Тогда мы смотрим, надо ли переназначать данной корове номер, а потом выбираем, как выгоднее: когда эта корова начинает новую группу(т.е. предыдущая из другой группы) или же она продолжает существующую группу(предыдущая из этой же группы).

178

(9 ответов, оставленных в Algo)

Не знаю, какая проблема с пейр, но перебирать ребра нужно по возрастанию веса, а не по убыванию.

179

(2 ответов, оставленных в Problems)

Можно развернуть систему координат на 45 градусов, тогда каждое звено ломаной будет параллельно одной из осей координат. Будем заметать вертикальной прямой слева направо и для каждого горизонтального отрезка создадим 2 события (начало и конец), а для вертикального - одно(проходим через него). Из условия видно, что 2 горизонтальных и 2 вертикальных отрезка между собой пересекаться не могут. Значит, все пересечения возможны только между одним вертикальным и одним горизонтальным отрезком. Значит, когда мы доходим до вертикального отрезка, нам нужно знать, сколько горизонтальных отрезков начались, но еще не закончились и в то же время, лежат в нужном диапазоне y-координат. Для этого, можно создать сумматор и для каждого у-ка хранить сколько начатых и еще не законченных отрезков с таким у-ком. Если координаты большие, то в начале следует сделать сжатие координат.
Сложность выходит O(NlogN) на сортировку и O(NlogN) на заметание, т.е. и суммарная сложность O(NlogN).

180

(30 ответов, оставленных в Problems)

Ну нам нужно добавить ограничение, что длина пути, заканчивающегося в корне поддерева должна быть неотрицательной, т.к. иначе мы просто можем вместо этого пути стартовать с данной вершины и это только улучшит ответ.

181

(30 ответов, оставленных в Problems)

Динамика то покатит(с маленьким изменением), а вот дфс от какой-то вершины, а потом еще один дфс из самой дальней уже не прокатит. Насколько я понял, вопрос был именно о втором.

182

(30 ответов, оставленных в Problems)

Вот контрпример(первые 2 числа - номера вершин, соединяемых ребром, 3-е - вес)
1 2 -1
2 3 -100
3 4 10
Если мы сделаем поиск от вершины 1, то самая дальняя будет 2, а самый длинный путь между 3 и 4.

183

(30 ответов, оставленных в Problems)

chum пишет:

сколько раз берем рандомную вершину?)

Один. Если веса ребер положительные, то помоему, это даже правильно. Объяснить можно так: каждое ребро веса А представим в виде цепочки из А ребер веса 1. Тогда получим дерево, где все ребра веса 1, а на нем этот алгоритм правильный.

Edit: Beaten smile

184

(30 ответов, оставленных в Problems)

brainail пишет:
KADR пишет:

Можно довольно простой динамикой по дереву сделать за О(Н).
Выделим какую-то вершину как корень и топологически отсортируем дерево. Теперь пусть f(v) это максимальный путь в поддереве с корнем в вершине v, такой что оба его конца лежат в этом поддереве, а g(v) это максимальный путь в поддереве с корнем в v, такой что один его конец это лист этого поддерева, а второй - вершина v.
Тогда f(v)=max(f(v')) для всех потомков. Но считая его так мы не учтем, что может быть путь как бы "соединяется" в вершине v, поэтому в этот max следует еще включить 2 потомка v1 и v2, для которых g(v1)+edge(v,v1)+g(v2)+edge(v,v2) - максимально. Это легко сделать за О(количество потомков).
g(v)=max(g(v')+edge(v,v')) для всех потомков.
Тогда f(корень) и будет ответом.

Я не спорю с тобой smile
Но ведь они не понимает ДВС или БФС со всех вершин,то и динамику не поймут я думаю.

Ну мне кажется, эта динамика проще чем дейкстра smile На самом деле все это делается в одном дфсе. Там выйдет строк 15-20, наверное.

185

(30 ответов, оставленных в Problems)

Можно довольно простой динамикой по дереву сделать за О(Н).
Выделим какую-то вершину как корень и топологически отсортируем дерево. Теперь пусть f(v) это максимальный путь в поддереве с корнем в вершине v, такой что оба его конца лежат в этом поддереве, а g(v) это максимальный путь в поддереве с корнем в v, такой что один его конец это лист этого поддерева, а второй - вершина v.
Тогда f(v)=max(f(v')) для всех потомков. Но считая его так мы не учтем, что может быть путь как бы "соединяется" в вершине v, поэтому в этот max следует еще включить 2 потомка v1 и v2, для которых g(v1)+edge(v,v1)+g(v2)+edge(v,v2) - максимально. Это легко сделать за О(количество потомков).
g(v)=max(g(v')+edge(v,v')) для всех потомков.
Тогда f(корень) и будет ответом.

186

(23 ответов, оставленных в Problems)

Ну заливку то понятно что можно решить быстрее, иначе задачу бы не предлагали smile Правда мне почему-то кажется что не стоит ее обсуждать, т.к. олимпиада все-таки еще идет.

187

(23 ответов, оставленных в Problems)

В общем случае думаю нет.

188

(23 ответов, оставленных в Problems)

Babushkin пишет:

Задачи как таковой нету, просто возник вопрос.

Часом не этой задачи как таковой нету?)

189

(2 ответов, оставленных в Algo)

Это можно сделать, например, так:
Пусть всего есть N вершин. Создадим новый граф, где каждой вершине V будет соответствовать пара V,V', причем номер вершины V' будет N+V. Если в изначальном графе вершина V была связана с W, тогда в новом графе добавим ребро из V в W'. Найдем в этом графе максимальное паросочетание. Тогда минимальное количество непересекающихся путей будет равно N-размер паросочетания.

190

(7 ответов, оставленных в Problems)

2rf пишет:

Просто размер максимального паросочетания равен размеру максимального независимого множества.

Разве размер макс. независимого это не N-MaxMatch, где N-кол-во вершин в графе, а MaxMatch - размер макс. паросочетания?
Размер макс. паросочетания равен размеру минимального покрывающего множества.

191

(2 ответов, оставленных в Problems)

Пусть нам известна высота нашей машины. Как тогда узнать, можно ли проехать за данную стоимость и не превысив данное время? Так как стоимость каждой дороги равна 1, мы можем для каждой вершины находить минимальное время за которое мы можем доехать до данной вершины, проехав ровно по К приватным дорогам. Тогда построим граф, где каждой вершиной будет пара - номер вершины в исходном графе и К. Вершин в таком графе будет N*N, т.к. нам не нужно проезжать более чем по N дорогам. Ребра будут идти между смежными вершинами, если требуемая высота не превышает данную, причем если дорога цены 0, тогда у вершин будет одинаковое К, иначе отличное на 1. Можно запустить алгоритм дейкстры на таком графе для нахождения кратчайшего пути от (S,0) до (T,K), где K - любое от 0 до min(N,money). Тогда если наименьшее время до хотя бы одной такой вершины не превышает maxtime, то при данной высоте проехать можно, иначе нельзя.
Ну а чтобы найти нужную высоту машины просто сделаем бинарный поиск.

192

(4 ответов, оставленных в Algo)

ScalAr пишет:

Когда то писал эту задачу, код сохранился. По моему, он решает не на минимум, а на максимум, но за O(N^3)

#include <cstdio>
#include <cstring>

const int MAX=701;
int a[MAX][MAX];
int n;
int x[MAX], y[MAX], sx[MAX], sy[MAX], mx[MAX], my[MAX];

inline int get(int x,int y)
{
        return a[x][y]-mx[x]-my[y];
}

bool go(int cur)
{
        sx[cur]=1;
        for(int i=0;i<n;i++)
        {
                if(get(cur,i)==0)
                {
                        if(y[i]==-1)
                        {
                                sy[i]=cur;
                                while(1)
                                {
                                        int t=x[cur];
                                        x[cur]=i;
                                        y[i]=cur;
                                        if(~t)
                                        {
                                                cur=sy[t];
                                                i=t;
                                        }
                                        else break;
                                }
                                return true;
                        }
                }
        }
        for(int i=0;i<n;i++)
        {
                if(get(cur,i)==0)
                {
                        if(!sx[y[i]])
                        {
                                sy[i]=cur;
                                if(go(y[i]))
                                {
                                        return true;
                                }
                        }
                }
        }
        return false;
}

int main()
{
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
                mx[i]=-50000;
                for(int j=0;j<n;j++)
                {
                        scanf("%d",&a[i][j]);
                        if(a[i][j]>mx[i])mx[i]=a[i][j];
                }
        }
        for(int i=0;i<n;i++)
        {
                int m=-50000;
                for(int j=0;j<n;j++)
                {
                        int t=get(j,i);
                        if(t>m)m=t;
                }
                my[i]=m;
        }
        memset(x,-1,sizeof x);
        memset(y,-1,sizeof y);
        for(int sc=0;sc<n;sc++)
        {
                memset(sx,0,sizeof sx);
                memset(sy,-1,sizeof sy);
                bool b=go(sc);
                while(!b)
                {
                        int m=-50000, dx;
                        for(int i=0;i<n;i++)
                        {
                                if(sx[i])
                                {
                                        for(int j=0;j<n;j++)
                                        {
                                                if(!(~sy[j]))
                                                {
                                                        int t=get(i,j);
                                                        if(m<t)
                                                        {
                                                                m=t;
                                                                dx=i;
                                                        }
                                                }
                                        }
                                }
                        }
                        for(int i=0;i<n;i++)
                        {
                                if(sx[i])mx[i]+=m;
                                if(~sy[i])my[i]-=m;
                        }
                        b=go(dx);
                }
        }
        for(int i=0;i<n;i++)
        {
                printf("%d ",x[i]+1);
        }
}

А какая разница, минимум или максимум? Можно все элементы домножить на -1 и тогда минимум превратится в максимум(и наоборот).

193

(4 ответов, оставленных в Algo)

Можно поподробнее?

194

(4 ответов, оставленных в Algo)

Есть матрица N*M состоящая из целых чисел. Требуется найти в ней прямоугольную подматрицу с максимальной суммой чисел.
Понятно как решить ее за O(N*M*M), но можно ли быстрее? Если нельзя в общем, то может можно для каких-то частных случаев?

195

(9 ответов, оставленных в Algo)

Раз нужно вывести все пути, проще всего запустить поиск в глубину из S. Помечать, использована ли данная вершина, не требуется, т.к. нам важно вывести все пути. Т.е. просто из текущей вершины запускаем поиск в глубину из всех смежных. Т.к в графе нету циклов, количество путей конечно и мы найдем все.

196

(13 ответов, оставленных в Algo)

Я находил статьи про Aztec Diamond, но связи с этой задачей я не вижу.

197

(13 ответов, оставленных в Algo)

На Тимусе есть такая задача
http://acm.timus.ru/problem.aspx?space=1&num=1594
Правда ее сдало всего 9 человек и я не из их числа. Интересно было бы узнать, как все-таки она делается.
В обсуждении есть формула, но в ней фигурируют синусы и косинусы, потому по ней считать нельзя.

198

(7 ответов, оставленных в Algo)

Ну диаметр дерева можно находить и просто 2-мя бфсами.

199

(10 ответов, оставленных в Offtopic)

Windows
Microsoft Visual Studio 2008
Microsoft C++ Compiler

Или

Ubuntu 9.04
CodeBlocks
gcc

200

(4 ответов, оставленных в Algo)

cerr<< выводит в stderr