POJ -2391 Ombrophobic Bovinos (+ Floyd + flujo de red bipartita)

Ombrophobic Bovinos

Tiempo límite:  1000MS   Límite de memoria:  65536k
Envíos totales:  21425   Aceptado:  4593

Descripción

Las vacas de FJ realmente odian mojarse tanto que el mero pensamiento de quedar atrapados en la lluvia los hace estrechan en sus cascos. Ellos han decidido poner una sirena de lluvia en la granja para hacerles saber cuando la lluvia se acerca. Tienen la intención de crear un plan de evacuación de la lluvia para que todas las vacas pueden llegar al refugio antes de que comience la lluvia. La predicción del tiempo no siempre es correcto, sin embargo. Con el fin de minimizar las falsas alarmas, que quieren hacer sonar la sirena lo más tarde posible sin dejar de dar tiempo suficiente para que todas las vacas para llegar a un refugio. 

La granja tiene campos F (1 <= F <= 200) en la que las vacas pastan. Un conjunto de P (1 <= P <= 1,500) caminos los conecta. Los caminos son anchas, de modo que cualquier número de vacas puede atravesar un camino en cualquier dirección. 

Algunos de los campos de la granja tienen refugios de lluvia bajo las cuales las vacas pueden protegerse. Estos refugios son de tamaño limitado, por lo que un solo refugio podría no ser capaz de mantener todas las vacas. Los campos que son pequeñas en comparación con los caminos y no requieren tiempo para las vacas para atravesar. 

Calcular la cantidad mínima de tiempo antes de que la lluvia comienza la sirena deben sonaban para que cada vaca puede llegar a un refugio.

Entrada

* Línea 1: Dos enteros separados por espacios: F y P 

* Líneas 2..F + 1: Dos enteros separados por un espacio que describen un campo. El primer número entero (rango: 0..1000) es el número de vacas en ese campo. El segundo número entero (rango: 0..1000) es el número de vacas el refugio en ese campo puede contener. Línea i + 1 se describen campo i. 

* Líneas F + 2..F + P + 1: Tres números enteros separados por un espacio que describen una trayectoria. Los primeros y segundos números enteros (tanto gama 1..F) dicen los campos conectados por el camino. El tercer número entero (rango: 1..1,000,000,000) es el tiempo que cualquier vaca lleva a atravesarlo.

Salida

* Línea 1: La cantidad mínima de tiempo que se requiere para todas las vacas a meterse debajo de un refugio, presumiendo que planificar sus rutas de forma óptima. Si no es posible para las todas las vacas a meterse debajo de un refugio, salida de "-1".

Ejemplo de entrada

3 4 
7 2 
0 4 
2 6 
1 2 40 
3 2 70 
2 3 90 
1 3 120

Ejemplo de salida

110

Insinuación

DETALLES DE SALIDA: 

En 110 unidades de tiempo, dos vacas desde el campo 1 pueden obtener bajo el refugio en ese campo, cuatro vacas desde el campo 1 pueden obtener bajo el refugio en el campo 2, y una vaca puede llegar al campo 3 y unirse a las vacas de esa campo bajo el refugio en el campo 3. Aunque hay otros planes que hará que todas las vacas en un refugio, ninguno lo hará en menos de 110 unidades de tiempo.

Fuente

USACO de 2005 marzo de Oro

 

Significado de las preguntas:

Hay n bloque de hierba, hierba en cada vaca, y el número de puntos puede llover número vaca escudo

Ym tienen ninguna conexión con cualquiera de los dos lados de la hierba, cada camino tiene una longitud fija, y se le preguntó si llueve, todo el ganado cómo llegar en el menor tiempo posible

Que todos los bovinos proceden punto de lluvia, si no es así, entonces la salida -1; pida el menor tiempo.

 

ideas:

nodo de pastizales, el borde de la carretera, una longitud lateral camino de longitud.

Floyd cantidad algoritmo de cálculo de la distancia más corta entre dos puntos cualquiera, entonces la media respuesta, la ejecución del flujo de red, el flujo de ganado

Si el flujo máximo> = el número de ganado, lo que indica que algún tiempo se puede acortar, aumentó lo contrario.

 

Red de diagrama de flujo: 

No dio una fuente súper fluya entre las vacas pastizales [i] 

Cada hierba virtualizado punto adicional i 'Flow inf 

prados de la hierba I y J virtual 'entre la velocidad de flujo de dis (i, j');

El tráfico de pastizales entre el punto de encuentro de la super (número de ganado puede blindar) refugio [i]

 

Tenga en cuenta que los datos van a estallar de largo long int 

[Código]

//#include <bits/stdc++.h>
#include <iostream>
#include <queue>
#include <string.h>
#include <stdio.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)

typedef long long ll;
const int maxn = 1e5+10;
const int mod =1e9+7;
const int inf = 0x3f3f3f3f;
const ll INF = 1e16;
using namespace std;
const int NMAX = 420;
const int EMAX = 82000;


int n,m;
int ne ,head[maxn];
int num[maxn],start,END,cnt,sum;
int cow[NMAX],shelter[NMAX];
ll mp[NMAX][NMAX];

struct node{
    int v,w,next; //u  v 从 u-v 权值为w
}edge[maxn];

void init()
{
    cnt = 0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
	/*
	根据题意建立有向图或无向图, 有向图反路0
	无向图反路一样
	*/
    edge[cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].next = head[u];
    head[u] = cnt++;

    edge[cnt].v = u;
    edge[cnt].w = 0;
    edge[cnt].next = head[v];
    head[v] = cnt++;
}
int bfs()
{
    queue<int>Q;
    memset(num,0,sizeof(num));
    num[start] = 1;
    Q.push(start);
    while(!Q.empty())
    {
        int t = Q.front();
        Q.pop();
        if(t==END)
            return 1;
        for(int i=head[t];i!=-1;i=edge[i].next)// 链式前向星访问找增广路
        {
            int t1 = edge[i].v;//下一个节点
            int t2 = edge[i].w;// 当前点 的流
            if(t2&&num[t1]==0)// 当前点存在 并且下一个点没有访问
            {
                num[t1]=num[t]+1;// 点=1
                if(t1==END)//  结束
                    return 1;// 存在
                Q.push(t1);
            }
        }
    }
    return 0;
}
int dfs(int u,int maxflow)
{
    if(u==END)
        return maxflow;
    int res = 0;  //从当前u点流出的流量
    for(int i = head[u];i!=-1;i = edge[i].next)
    {
        int t1 = edge[i].v;// 下一个节点
        int t2 = edge[i].w;// 当前节点的流
        if(t2&&num[t1] == num[u]+1)
        {
            int temp = dfs(t1,min(maxflow-res,t2));// 选择流 小的一部分
            edge[i].w-=temp;// 正向减少
            edge[i^1].w+=temp;//反向增加
            res += temp;
            if(res==maxflow)
                return res;//已达到祖先的最大流,无法再大,剪枝
        }
    }
    if(!res)
        num[u] = -1;//此点已无流,标记掉
    return res;
}
ll Dinic(int s,int ed)
{
    ll ans = 0;
    while(bfs()) //有增广路
    {
        ans+=dfs(s,inf);
    }
    return ans;
}

void floyd()
{
	for(int  k = 1; k <= n ;k++)
	{
		for(int  i = 1 ; i <= n;i++)
		{
			for(int j = 1 ;j <= n;j++)	
			{ 
				if( mp[i][k] + mp[k][j] <  mp[i][j])
				{
					mp[i][j]  = mp[i][k] + mp[k][j];
				}
			}
		}
	}
}
int main(int argc, char const *argv[])
{
	int u,v;
	ll sum,w;
	while(~scanf("%d %d",&n,&m))
	{
		END = 2*n+1;start = 0;
		
		for(int i = 1 ;i <= n ; i++)
			for(int j = 1 ;j <= n ; j++)
					mp[i][j] = INF;
		sum =  0;
		for(int i = 1; i <= n ; i++)
		{
			scanf("%d %d",&cow[i],&shelter[i]);
			sum += cow[i];
		}
		
		while(m--)
		{
			scanf("%d %d %lld",&u,&v,&w);
			if( w < mp[u][v] )
			{
				mp[u][v] = mp[v][u] = w;
			}
		}
		floyd();

		ll mid ,low = 0, high = INF-1 ,ans = -1;
		
		while( low < high)
		{
			mid = (low + high )>>1;
			init();
			for(int i = 1 ;i <= n;i++)
			{
				addedge(0,i,cow[i]);
				addedge(i,i+n,inf);
				addedge(i+n,2*n+1,shelter[i]);
				for( int j = i+ 1 ; j <= n ;j++)
				{
					if(mp[i][j] <= mid)
					{
						addedge(i,j+n,inf);
						addedge(j,i+n,inf);
					}
				}
			}
			ll te = Dinic(0,2*n+1);
			//cout<<te<<" Dinic "<<sum<<" "<<mid<<endl;
			if(  te>= sum)
			{
				ans = mid;
				high = mid;
			}
			else 
				low = mid + 1;
		}
		printf("%lld\n",ans);
	}
	return 0;
}
/*
	3 4
	7 2
	0 4
	2 6
	1 2 40
	3 2 70
	2 3 90
	1 3 120
 */

 

Publicados 372 artículos originales · ganado elogios 89 · Vistas de 230.000 +

Supongo que te gusta

Origin blog.csdn.net/sizaif/article/details/83110155
Recomendado
Clasificación