uva1599 bfs的倒序思路和稀疏图的表示方法

此题卡了2天
try1:看题不仔细,题目说颜色可以超过10,误以为只能是一位数字,用string去存储,导致错误。还有它是输入多组数据呀

try2:用一个bfs去做,从1开始,结构体里保存目前为止的颜色序列,wa了,还不知道原因。
这也要反思看到bfs题目,不仅要想到正序列,还要想到倒序。

try3:参照网上代码–https://blog.csdn.net/pb1995/article/details/49531075
这个代码真的很神,有很多技巧吧。
1.题目时求已知起点和终点的多条最短路,用倒bfs更快。
第二阶段在已标记步数的地图中走一条颜色序列最小的,由于是倒bfs过来的,所以从任何有标有步数的地图块中都可走回去,且颜色长度已经固定,因此在step=a这个集合中,我们要从中选择一个颜色序列最小的,如果存在颜色序列相同的,就再比较它们各自的下一个的颜色序列大小。
经验:要理清倒bfs的潜在逻辑。

2.用 map<int,map<int,int> >来做地图的好处,在长宽很大,而是稀疏点图的时候,又需要再带一个属性,这时候用这个比vector加结构体好用。

3.set<vector >a 原来可以使用,vector可以直接等于vecotor,不定长时存char可以用string,存数字用vecotor。

4.对于大图用dfs会慢很多,还是用bfs。

ac代码

#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
const int maxn=1e5+10;
map<int,map<int,int> >mp;
int distant[maxn],room;
bool vi[maxn];
struct re{int x,step;
re(int a,int b){x=a,step=b;}
};

void  bfs1()
{
    memset(vi,0,sizeof(vi));
    memset(distant,0,sizeof(distant));
queue<int>all;
all.push(room);
vi[room]=1;
distant[room]=1;
while(!all.empty())
{int now=all.front();
all.pop();
map<int,int> ::iterator it1=mp[now].begin();
for( ;it1!=mp[now].end(); it1++)
{
if(vi[it1->first]==0)
{
    vi[it1->first]=1;
    all.push(it1->first);
    distant[it1->first]=distant[now]+1;
    if(vi[1]!=0)return;
}
}

}
//for(int i=1;i<=room;i++){printf("i=%d  distant=%d\n",i,distant[i]);}
}
//bool Lessthan(int *path1,int *path2)
//{while(*path1++ == *path2++);return *path1<*path2;}
void bfs2()
{ int k=1;
memset(vi,0,sizeof(vi));

vector<int>num,newnum,ans;
num.push_back(1);
vi[1]=1;
    for(int i=distant[1];i>1;i--){
    int micolr=1e9+10;
    for(int f=0;f<num.size();f++){
            k=num[f];
    map<int,int> ::iterator it3=mp[k].begin();

    for(;it3!=mp[k].end();it3++)
    {   int g=it3->first;
        int f=it3->second;
        if(vi[g]==0&&distant[g]==i-1)micolr=min(f,micolr);
    }
    }
    ans.push_back(micolr);
    for(int f=0;f<num.size();f++)
    {k=num[f];
        map<int,int> ::iterator it3=mp[k].begin();

    for(;it3!=mp[k].end();it3++)
    {int g=it3->first;
    int f=it3->second;
    //printf("g=%d  f=%d\n",g,f);
        if(f==micolr&&distant[g]==(i-1)&&vi[g]==0){newnum.push_back(g);vi[g]=1;}
    }
    }
    //for(int i=0;i<newnum.size();i++)
      //  printf("%d ",newnum[i]);
    //printf("kkkkk\n");
    num=newnum;
    newnum.clear();

}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++)
    printf("%d%s",ans[i],i==(ans.size()-1)? "\n":" ");
}
int main(void)
{int n;
//freopen("123.txt","r",stdin);
    while(scanf("%d %d",&room,&n)!=EOF)
    {mp.clear();
        for(int i=1;i<=n;i++)
        {
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            if(mp[a][b]==0||mp[a][b]>c)
            {
                mp[a][b]=c;
                mp[b][a]=c;
            }
        }
        bfs1();
        bfs2();
    }
    return 0;
}

未知wa在哪的代码,用一次bfs的

#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<string>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=100009;
int room;
struct re
{
    int th;
    vector<int>col;
};

struct point
{
    int x,y;
    point(int a,int b)
    {
        x=a;
        y=b;
    }
    bool operator<(const point &f)const
    {
        return x==f.x? y<f.y:x<f.x;
    }
};
//point pp;
vector<point>all[maxn];
set<vector<int> >answ;
bool vi[maxn];
int minlen;
int mintotal;
void bfs()
{
    queue<re>total;
    re tem;
    tem.th=1;
    vi[1]=1;
    total.push(tem);
    int ti=0;
    while(!total.empty())
    {
        re now=total.front();
        // printf("th=%d\n",now.th);
        total.pop();
        int minum=0;
        for(int i=0; i<all[now.th].size(); i++)
        {
            int k=all[now.th][i].x;

            if(vi[k]==0)
            {
                //printf("%d  %d\n",k,all[now.th][i].y);
                minum++;
                re tem;
                vi[k]=1;
                vi[room]=0;
                tem.col.assign(now.col.begin(),now.col.end());
                tem.col.push_back(all[now.th][i].y);
                tem.th=k;
                total.push(tem);
                if(tem.col.size()>minlen)
                    return ;
                if(k==room)
                {
                    answ.insert(tem.col);
                    // printf("%d  %d  minlen=%d mintotal=%d\n",tem.th,all[now.th][i].y,minlen,mintotal);
                    ti++;
                    if(ti>=mintotal)
                        return;
                }

            }
        }



    }
}
int main(void)
{
    int n;
//freopen("123.txt","r",stdin);
    while(scanf("%d %d",&room,&n)!=EOF)
    {memset(vi,0,sizeof(vi));
        map<point,int>check;
        mintotal=0;
        minlen=maxn*2;
        for(int i=1; i<=n; i++)
        {
            int a,b,c;
            scanf("%d %d%d",&a,&b,&c);
            if(a>b)
                swap(a,b);
            if(b==room)
                mintotal++;
            point pp(a,b);
            if(check.count(pp)==0)
            {all[a].clear();
            all[b].clear();
                check[pp]=c;
            }
            else
            {
                if(check[pp]>c)
                {
                    check[pp]=c;
                }
            }
        }
        map<point,int>::iterator it=check.begin();
        for(; it!=check.end(); it++)
        {
            //printf("%d    %d   %d\n",it->first.x,it->first.y,it->second);
            all[it->first.x].push_back(point(it->first.y,it->second));
            all[it->first.y].push_back(point(it->first.x,it->second));
        }


        bfs();
        set< vector<int> >::iterator it2=answ.begin();
        vector<int>yy;
        // for(;it2!=answ.end();it2++){
        yy.assign(it2->begin(),it2->end());
        cout <<yy.size()<<endl;
        for(int i=0; i<yy.size(); i++)
            printf("%d%s",yy[i],i==yy.size()-1 ?"\n":" ");
        //  }
        answ.clear();
        //for(int i=1; i<=n; i++)all[i].clear();
    }
    return 0;

}

猜你喜欢

转载自blog.csdn.net/qq_43235540/article/details/87027154
今日推荐