Cod sursa(job #170077)

Utilizator DorinOltean Dorin Dorin Data 2 aprilie 2008 13:11:24
Problema Gather Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.34 kb
# include <stdio.h>
# include <fstream>
# include <vector>

using namespace std;

# define input "gather.in"
# define output "gather.out"

# define max 16
# define INF 1<<31
# define maxN 751

unsigned long n,m,k,j,p[max],x,y,cap,rez,cost,c,i;
unsigned long d[max][max][max];
unsigned long r,ok,e,res;
long dist[maxN];
unsigned long fi[1<<max][max];
unsigned long nr[1 << max][max+1];
long pos;


struct muchie
{
       unsigned int x,y,l,c;
};

struct cmp
{
	   bool operator()(muchie a,muchie b)
	   {
			if( a.c < b.c )
			   return 1;
			if( a.c > b.c )
				return 0;
			return a.l < b.l;
	   }
};

vector <muchie> a;

int main()
{
	freopen(input,"r",stdin);
	freopen(output,"w",stdout);

	scanf("%ld%ld%ld",&k,&n,&m);
    for(i=0;i<k;i++)
       scanf("%ld",&p[i]);

	for(i=1;i<=m;i++)
	{
		scanf("%ld%ld%ld%ld",&x,&y,&cost,&cap);

		muchie aux;
		aux.x = x;
		aux.y = y;
		aux.l = cost;
		aux.c = cap;
		a.push_back(aux);
    }
    
    sort(a.begin(),a.end(),cmp());

    pos = m-1;
    long c;

    for(c = k-1; c>=0; c--)
    {
        while(pos >= 0 && a[pos].c >= c+1 ) pos--;
        for(r=0;r<k;r++)
        {
            for(j=1;j<=n;j++)
                dist[j] = INF;
            i = p[r];
			dist[i] = 0;
            
            for(ok = 1,i = 1;i <= m&& ok;i++)
                   for(ok = 0,j=pos + 1;j<m;j++)
                   {
                          x = a[j].x;
                          y = a[j].y;
                          if(dist[y] > dist[x] + a[j].l)
                              dist[y] = dist[x] + a[j].l, ok = 1;
                          if(dist[x] > dist[y] + a[j].l)
                              dist[x] = dist[y] + a[j].l, ok = 1;
                   }
            for(i=0;i<k;i++)
               d[c][r][i] = dist[p[i]];
        }
    }
    
    for(i = 1; i <= n ; i++)
        dist[i] = INF;
    dist[1] = 0;
    for(ok = 1, i = 1;i <= n && ok ; i++)
        for( ok = 0, j = 0; j < m; j++)    
        {
             x = a[j].x;
             y = a[j].y;
             if(dist[y] > dist[x] + a[j].l)
                 dist[y] = dist[x] + a[j].l, ok = 1;
             if(dist[x] > dist[y] + a[j].l)
                 dist[x] = dist[y] + a[j].l, ok = 1;
        }
               
    unsigned long sz,count;
        
    for(i=1; i < (1 << k); i++)
    {
       int aux = i;
       sz = 0,count=0;
       while(aux)
       {
           fi[i][count] = INF;
           if(aux&1)
              nr[i][++sz] = count;
           count ++;
           aux >>= 1;
       }
       while ( count < k ) fi[i][count] = INF, count++;
       nr[i][0] = sz;
    }
    
     for(i = 0;i < k; i ++)
        fi[1<<i][i] = dist[p[i]];
    
    for(r = 1;r < (1 << k); r++)
    {
          sz = nr[r][0];
          for( e = 1; e <= sz; e++)
          {
			   j = nr[r][e];
               for(x = 1; x <= sz; x++)
               {
					 i = nr[r][x];
                     if(i != j)
					 {
						long ii = r^(1 << j);
						unsigned long x = (sz) * d[sz-2][i][j] + fi[ii][i];
						  if(fi[r][j] > x)
							 fi[r][j] = x;
                     }
               }
          }
    }
    
    res = INF;
    
    for(i=0;i<k;i++)
       if(res > fi[(1<<k)-1][i])
          res = fi[(1<<k)-1][i];
          
    printf("%d",res);
          
	return 0;
}