Aizu 2541 Magical Bridges

来源:互联网 发布:天刀捏脸数据成男网盘 编辑:程序博客网 时间:2024/06/04 19:22

题意:
n个岛屿,由m条桥连接,其中有k条是魔法桥,你可以用魔法把他们变成相同长度。
求在执行魔法后,两个起点S1和S2到终点T的最短路的最小绝对差。
1n10001m20001k100

S1S2T的最短路将会是如 j×x+dis 的形式。x为相同长度,j为该最短路上魔法桥的个数,因为魔法桥的个数特别少,所以可以直接暴力转移。

理解一:
画出所有的直线,现在等价于求多条射线的最低点。
利用线段交暴力即可。
用是spfa进行预处理,每个点可以得到最多k条直线,暴力求交点的复杂度O(k2)
最后要判断最低点,除去spfa处理外,复杂度为O(k3)
本文代码就是这样的方法,但是姿势丑陋。附上S菊苣代码.
理解二:
当然也可以这么理解,对于每一个j,我们必须保证的是其他所有的可能魔法桥个数,关于dis[u][j]+j×xdis[u][k]+k×x。因此有n1个方程,求出可能的x的区间[L,R]
此复杂度为O(k2)
然后在[Lj,Rj][Lk,Rk]中暴力扫描整数点的值,带入求出min{dis[s1][j]}min{dis[s2][k]}

//      whn6325689//      Mr.Phoebe//      http://blog.csdn.net/u013007900#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#include <functional>#include <numeric>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define eps 1e-9#define PI acos(-1.0)#define INF 0x3f3f3f3f#define LLINF 1e18#define speed std::ios::sync_with_stdio(false);typedef long long ll;typedef unsigned long long ull;typedef long double ld;typedef pair<ll, ll> pll;typedef complex<ld> point;typedef pair<int, int> pii;typedef pair<pii, int> piii;typedef vector<int> vi;#define CLR(x,y) memset(x,y,sizeof(x))#define CPY(x,y) memcpy(x,y,sizeof(x))#define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))#define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))#define debug(a) cout << #a" = " << (a) << endl;#define debugarry(a, n) for (int i = 0; i < (n); i++) { cout << #a"[" << i << "] = " << (a)[i] << endl; }#define mp(x,y) make_pair(x,y)#define pb(x) push_back(x)#define lowbit(x) (x&(-x))#define MID(x,y) (x+((y-x)>>1))#define ls (idx<<1)#define rs (idx<<1|1)#define lson ls,l,mid#define rson rs,mid+1,rtemplate<class T>inline bool read(T &n){    T x = 0, tmp = 1;    char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;}template <class T>inline void write(T n){    if(n < 0)    {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n)    {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);}//-----------------------------------ll n,m,s[3],t;bool vis[1010][111];ll dis[1010][111],mi[3];double val[100010];char str[22];struct Edge{    ll to,next,w;} e[40010];int head[1010],tot,mag,num;void init(){    CLR(head,-1);    tot=mag=num=0;}void addedge(ll u,ll v,ll w){    e[tot].to=v;    e[tot].w=w;    e[tot].next=head[u];    head[u]=tot++;}void spfa(ll s){    queue<pll> q;    CLR(dis,-1);CLR(vis,0);    while(!q.empty())   q.pop();    dis[s][0]=0;vis[s][0]=1;    q.push(mp(s,0));    while(!q.empty())    {        pll tmp=q.front();        q.pop();        ll u=tmp.first,tim=tmp.second,v;        vis[u][tim]=false;        for(int i=head[u]; ~i; i=e[i].next)        {            v=e[i].to;            ll k,w;            if(e[i].w==-1)  w=0,k=1;            else    w=e[i].w,k=0;            if(tim+k<=mag && (dis[v][tim+k]==-1 || dis[v][tim+k]>dis[u][tim]+w))            {                dis[v][tim+k]=dis[u][tim]+w;                if(!vis[v][tim+k])                {                    vis[v][tim+k]=true;                    q.push(mp(v,tim+k));                }            }        }    }}int main(){    ll u,v,w;    while(read(n)&&read(m)&&read(s[1])&&read(s[2])&&read(t)&&(n+m))    {        init();        for(int i=0; i<m; i++)        {            scanf("%lld %lld %s",&u,&v,str);            if(str[0]=='x')            {                addedge(u,v,-1);                addedge(v,u,-1);                mag++;            }            else            {                sscanf(str,"%lld",&w);                addedge(u,v,w);                addedge(v,u,w);            }        }        spfa(t);        val[num++]=0;        for(int i=1; i<=2; i++)        {            for(int j=0; j<mag; j++)            {                ll minn=dis[s[i]][j];                if(minn==-1)    continue;                for(int k=j+1; k<=mag; k++)                {                    ll maxx=dis[s[i]][k];                    if(maxx==-1)    continue;                    double w=1.0*(maxx-minn)/(j-k);                    if(w>0) val[num++]=w;                }            }        }        for(int j=0; j<=mag; j++)        {            ll minn=dis[s[1]][j];            if(minn==-1)    continue;            for(int k=0; k<=mag; k++)            {                if(j==k)    continue;                ll maxx=dis[s[2]][k];                if(maxx==-1)    continue;                double w=1.0*(maxx-minn)/(j-k);                if(w>0) val[num++]=w;            }        }        ll ans=LLINF;        for(int i=0; i<num; i++)        {            for(int j=1; j<=2; j++)            {                mi[j]=LLINF;                for(int k=0; k<=mag; k++)                    if(~dis[s[j]][k])                        mi[j]=min(mi[j],dis[s[j]][k]+k*(ll)(val[i]+eps));            }            ans=min(ans,abs(mi[1]-mi[2]));        }        for(int i=0; i<num; i++)        {            for(int j=1; j<=2; j++)            {                mi[j]=LLINF;                for(int k=0; k<=mag; k++)                    if(~dis[s[j]][k])                        mi[j]=min(mi[j],dis[s[j]][k]+k*(ll)(val[i]+1+eps));            }            ans=min(ans,abs(mi[1]-mi[2]));        }        printf("%lld\n",ans);    }    return 0;}
0 0
原创粉丝点击