【2016-CCPC-B】强连通分量,tarjan(Bomb,hdu 5934)
2016-10-29 21:54
507 查看
打了网上的重现赛,一直TLE+WA一度怀疑方法的问题,然后到最后也没找到,但发现了很多至关重要的小错误。
比如把边的序号当成点用,边的空间没开够等等等等。
赛后重写了,直接AC。
比赛很多时候就是这样,刚接触一道新的题目,先要思考一段时间,然后再编写程序,这些过程都是很生涩的,路途坑坑洼洼会有很多小障碍,而且没AC就得反复debug和修改,会把程序改得很乱,而且自己也会疲惫,然后往往就最后没过。只能说不够熟练,没有什么差一点点,只有付出的不够多,没有练到炉火纯青,顺手拈来的地步,而这是需要长时间大量的练习的。重写也是一个不错的选择,因为可能程序一开始就没写好,然后又被你改得乱七八糟,很多小细节是难以发现的。不如趁着思考了那么久,有着比较清晰的思路,去重写一份精炼的代码,不但可能会更注意细节,从而解决一些本就不应该出现的难以发现的bug,而且新的代码更加整洁,容易debug。
当时TLE就一直优化,连什么输入输出都优化了。。。然并卵,其实就是数组开的不够大之类的一些乱七八糟的错误吧,反正最后没找到。
代码
#include<bits/stdc++.h>
#define maxn 1010
#define INF 0X3F3F3F3F
using namespace std;
struct bomb
{
int x,y,r,c;
}B[maxn];
int N;
struct edge
{
int to,next;
}edges[maxn*maxn];
int tot,head[maxn];
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edges[tot].to=v;
edges[tot].next=head[u];
head[u]=tot++;
}
inline double dist(int i,int j)
{
double x=B[i].x-B[j].x;
double y=B[i].y-B[j].y;
return sqrt(x*x+y*y);
}
////////////////////////////
int dfn[maxn],low[maxn];
int cnt,num;
bool is[maxn];
int cost[maxn];
int belong[maxn];
stack<int>s;
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
is[u]=true;
s.push(u);
for(int i=head[u];i!=-1;i=edges[i].next)
{
int v=edges[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(is[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
num++;
while(s.top()!=u)
{
belong[s.top()]=num;
is[s.top()]=false;
cost[num]=min(cost[num],B[s.top()].c);
s.pop();
}
belong[s.top()]=num;
is[s.top()]=false;
cost[num]=min(cost[num],B[s.top()].c);
s.pop();
}
}
////////////////////////////
int id[maxn];
int solve()
{
memset(dfn,0,sizeof(dfn));
memset(id,0,sizeof(id));
memset(cost,INF,sizeof(cost));
cnt=num=0;
for(int i=1;i<=N;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=N;i++)
for(int j=head[i];j!=-1;j=edges[j].next)
{
int v=edges[j].to;
int x=belong[i];
int y=belong[v];
if(x!=y) id[y]++;
}
int ans=0;
for(int i=1;i<=num;i++)
if(!id[i]) ans+=cost[i];
return ans;
}
int main()
{
int T;
scanf("%d",&T);
for(int t=1;t<=T;t++)
{
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d %d %d %d",&B[i].x,&B[i].y,&B[i].r,&B[i].c);
init();
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(i!=j&&dist(i,j)<=B[i].r)
addedge(i,j);
printf("Case #%d: %d\n",t,solve());
}
return 0;
}
比如把边的序号当成点用,边的空间没开够等等等等。
赛后重写了,直接AC。
比赛很多时候就是这样,刚接触一道新的题目,先要思考一段时间,然后再编写程序,这些过程都是很生涩的,路途坑坑洼洼会有很多小障碍,而且没AC就得反复debug和修改,会把程序改得很乱,而且自己也会疲惫,然后往往就最后没过。只能说不够熟练,没有什么差一点点,只有付出的不够多,没有练到炉火纯青,顺手拈来的地步,而这是需要长时间大量的练习的。重写也是一个不错的选择,因为可能程序一开始就没写好,然后又被你改得乱七八糟,很多小细节是难以发现的。不如趁着思考了那么久,有着比较清晰的思路,去重写一份精炼的代码,不但可能会更注意细节,从而解决一些本就不应该出现的难以发现的bug,而且新的代码更加整洁,容易debug。
当时TLE就一直优化,连什么输入输出都优化了。。。然并卵,其实就是数组开的不够大之类的一些乱七八糟的错误吧,反正最后没找到。
代码
#include<bits/stdc++.h>
#define maxn 1010
#define INF 0X3F3F3F3F
using namespace std;
struct bomb
{
int x,y,r,c;
}B[maxn];
int N;
struct edge
{
int to,next;
}edges[maxn*maxn];
int tot,head[maxn];
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edges[tot].to=v;
edges[tot].next=head[u];
head[u]=tot++;
}
inline double dist(int i,int j)
{
double x=B[i].x-B[j].x;
double y=B[i].y-B[j].y;
return sqrt(x*x+y*y);
}
////////////////////////////
int dfn[maxn],low[maxn];
int cnt,num;
bool is[maxn];
int cost[maxn];
int belong[maxn];
stack<int>s;
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
is[u]=true;
s.push(u);
for(int i=head[u];i!=-1;i=edges[i].next)
{
int v=edges[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(is[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
num++;
while(s.top()!=u)
{
belong[s.top()]=num;
is[s.top()]=false;
cost[num]=min(cost[num],B[s.top()].c);
s.pop();
}
belong[s.top()]=num;
is[s.top()]=false;
cost[num]=min(cost[num],B[s.top()].c);
s.pop();
}
}
////////////////////////////
int id[maxn];
int solve()
{
memset(dfn,0,sizeof(dfn));
memset(id,0,sizeof(id));
memset(cost,INF,sizeof(cost));
cnt=num=0;
for(int i=1;i<=N;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=N;i++)
for(int j=head[i];j!=-1;j=edges[j].next)
{
int v=edges[j].to;
int x=belong[i];
int y=belong[v];
if(x!=y) id[y]++;
}
int ans=0;
for(int i=1;i<=num;i++)
if(!id[i]) ans+=cost[i];
return ans;
}
int main()
{
int T;
scanf("%d",&T);
for(int t=1;t<=T;t++)
{
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d %d %d %d",&B[i].x,&B[i].y,&B[i].r,&B[i].c);
init();
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(i!=j&&dist(i,j)<=B[i].r)
addedge(i,j);
printf("Case #%d: %d\n",t,solve());
}
return 0;
}
相关文章推荐
- 2016ccpc杭州赛 hdu 5934 B.Bomb
- HDU 5934 && 2016CCPC杭州 B: Bomb(Trajan强连通)
- [hdu 5934 Bomb]Tarjan强连通分量
- 【(最小权点基)tarjan强连通分量缩点+tarjan模板】HDU 5934 Bomb
- 2016ccpc杭州赛 hdu 5934 K.Kingdom of Obsession
- HDU 5934 Bomb(强连通分量)
- hdu 5934 Bomb【最小点基----Tarjan强连通+缩点染色】
- HDU-5934 Bomb(tarjan缩点+入度0最小和)
- HDU 5934 Bomb(tarjan缩点)
- -----tarjan强连通分量缩点-hdu 5934 -Bomb
- HDU 5934 Bomb (tarjan缩点)
- Bomb (hdu 5934 && 2016icpc杭州现场赛题目)
- HDU 5832——A water problem & 2016CCPC网络赛1001
- 2016 ccpc 合肥 HDU 5961 传递
- HDU 5934 强连通分量
- HDU 5918 Sequence I (2016-ccpc-长春)
- 【HDU 5934】Bomb(强连通缩点)
- (HDU 5926)Mr. Frog’s Game 水题 <2016CCPC东北地区大学生程序设计竞赛 - 重现赛 >
- 2016 ccpc 合肥 HDU 5963 朋友
- 2016 ccpc长春现场赛I Sequence I(hdu 5918)