您的位置:首页 > 其它

BZOJ2707 [SDOI2012]走迷宫

2016-07-07 19:54 337 查看
设f[i]表示从第i个点走到终点的期望,d[i]表示i的出度,j是第i个点能走到的点

则f[i]=sigma (f[j]+1)/d[i]

在数据范围小的情况下,我们可以高斯消元求出f数组

由于本题中每个边双大小<=100,把边双缩点之后的图是有拓扑序的,所以我们可以按拓扑序求,每个边双内高斯消元

不过这复杂度上限不是100^4的么……反正能过……

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
#include<vector>
#include<set>
using namespace std;
#define MAXN 10010
#define MAXM 1000010
#define INF 1000000000
#define MOD 1000000007
#define ll long long
#define eps 1e-8
struct vec{
int to;
int fro;
};
struct G{
vec mp[MAXM];
int tai[MAXN],cnt;
inline void be(int x,int y){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
}
void dfs(int x);
void build();
void cal(int x);
void get(int x);
};
G g,ng;
bool ist[MAXN];
int st[MAXN],tp;
int dfn[MAXN],ndf[MAXN],low[MAXN],tim;
int bel[MAXN],siz[MAXN],tot;
int n,m;
vector<int>ps[MAXN];
bool vis[MAXN],VIS[MAXN];
double f[MAXN];
int d[MAXN];
int S,T;
int lst[110][110];
double a[110][110];
void G::dfs(int x){
int i,y;
dfn[x]=low[x]=++tim;
ist[st[++tp]=x]=1;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(!dfn[y]){
dfs(y);
low[x]=min(low[x],low[y]);
}else if(ist[y]){
low[x]=min(low[x],dfn[y]);
}
}
if(low[x]==dfn[x]){
int t=0;
tot++;
while(t!=x){
ist[t=st[tp--]]=0;
siz[bel[t]=tot]++;
ps[tot].push_back(t);
}
}
}
void G::build(){
int i,x,y;
for(x=1;x<=n;x++){
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(bel[x]!=bel[y]){
ng.be(bel[x],bel[y]);
}
}
}
}
void jud(int x,int y){
if(lst[x][y]!=tim){
a[x][y]=0;
}
lst[x][y]=tim;
}
void G::get(int x){
int i,y;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(VIS[y]){
jud(dfn[x],tot+1);
a[dfn[x]][tot+1]+=1.0*(f[y]+1)/d[x];
}else{
jud(dfn[x],dfn[y]);
jud(dfn[x],tot+1);
a[dfn[x]][tot+1]+=1.0/d[x];
a[dfn[x]][dfn[y]]-=1.0/d[x];
}
}
}
void gs(){
int i,j,k;
for(i=1;i<=tot;i++){
jud(i,i);
if(fabs(a[i][i])<eps){
for(j=i+1;j<=tot;j++){
jud(j,i);
if(fabs(a[j][i]>eps)){
for(k=1;k<=tot+1;k++){
jud(i,k);
jud(j,k);
swap(a[i][k],a[j][k]);
}
}
}
}
if(fabs(a[i][i]>eps)){
for(j=1;j<=tot;j++){
if(i!=j){
jud(j,i);
double t=a[j][i]/a[i][i];
for(k=1;k<=tot+1;k++){
jud(i,k);
jud(j,k);
a[j][k]-=t*a[i][k];
}
}
}
}
}
}
void G::cal(int x){
int i,y;
if(vis[x]){
return ;
}
vis[x]=1;
for(i=tai[x];i;i=mp[i].fro){
cal(mp[i].to);
}
tot=0;
tim++;
for(i=0;i<ps[x].size();i++){
ndf[++tot]=ps[x][i];
dfn[ps[x][i]]=tot;
jud(tot,tot);
a[tot][tot]=1;
}
for(i=0;i<ps[x].size();i++){
g.get(ps[x][i]);
}
gs();
for(i=1;i<=tot;i++){
jud(i,i);
if(fabs(a[i][i])<eps){
printf("INF\n");
exit(0);
}
f[ndf[i]]=a[i][tot+1]/a[i][i];
VIS[ndf[i]]=1;
}

}
int main(){
int i,x,y;
scanf("%d%d%d%d",&n,&m,&S,&T);
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
if(x!=T){
g.be(x,y);
d[x]++;
}
}
g.dfs(S);
for(i=1;i<=n;i++){
if(i!=T){
if(dfn[i]&&(!d[i])){
printf("INF\n");
return 0;
}
}else{
if(!dfn[i]){
printf("INF\n");
return 0;
}
}
}
g.build();
vis[bel[T]]=1;
VIS[T]=1;
ng.cal(bel[S]);
printf("%.3lf\n",f[S]);
fclose(stdin);
fclose(stdout);
return 0;
}

/*

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: