This is my solution to solve in O(N) the graphs:
#include
#include
#include
typedef long long ll;
void fs_int(int *x) {
register int c = getchar_unlocked();
*x = 0;
int neg = 0;
for(; ((c<48 || c>57) && c != '-'); c = getchar_unlocked());
if(c=='-') {
neg = 1;
c = getchar_unlocked();
}
for(; c>47 && c<58 ; c = getchar_unlocked()) {
*x = (*x<<1) + (*x<<3) + c - 48;
}
if(neg)
*x = -(*x);
}
typedef struct {
int next;
int val;
int d;
}List;
typedef struct
{
int parent;
int shrt;
ll count;
int on_reg;
int ch;
} Node;
#define MOD 1000000007
ll get_sum(Node *tr,List *l)
{
Node *t, *t2;
int i,j,n=0,fix;
ll result;
static int *reg=NULL,sz=1000;
if (!reg)
reg=malloc(sizeof(int)*sz);
reg[n++]=1;
int cur_d;
while(n)
{
///fix is the limit for the for, it is the shortname of "for ix" :
// from 0 to fix there are the old values, from fix to n there are the new ones
fix=n;
for (i=0;i<fix;i++)
{
//the better way to reduce the complexity is shift the last item to the current one
t=&tr[reg[i]];
reg[i--]=reg[--fix];
reg[fix]=reg[--n];
t->on_reg=0;
///this scores all the edges from departing from this node
///the criteria to avoid propagation is the key of the program
for (j=t->ch;j;j=l[j].next)
{
if (l[j].val==1) //avoid the root
continue;
t2=&tr[l[j].val]; //store in some comfortable variable
cur_d=t->shrt+l[j].d;
if (t2->shrt!=0 && t2->shrt< cur_d ) ///if my path is heaviest nothing to do
continue;
else if (t2->shrt ==cur_d) //I found an item with same weight. It was required to count them
t2->count++;
else if (t2->shrt==0 || t2->shrt>cur_d) //found a unexplored item or my path is lighter
{
t2->shrt=cur_d;
t2->count=1;
if (!t2->on_reg) //if not already in the reg, I insert it inside
{
if (n>=sz)
{
sz<<=1;
reg=realloc(reg, sizeof(int)*sz);
}
reg[n++]=l[j].val; //at position n
t2->on_reg=1;
}
}
}
/* printf ("reg: ");
for (k=0;k<n;k++)
printf ("%d ",reg[k]);
printf ("\n");*/
}
}
//printf ("\n");
return result;
}
typedef long long ll;
void set_depth(Node *tr, List *l, int rt,int cd,int parent)
{
int i;
tr[rt].parent=parent;
for (i=tr[rt].ch;i;i=l[i].next)
if (l[i].val== parent )
continue;
else
set_depth(tr,l,l[i].val,cd+1,rt);
}
int main ()
{
int t,n,q,i,u,v,d;
fs_int(&t);
int il=1;
Node tr[100005];
List l[200005];
List *tl;
while (t--)
{
fs_int(&n);
fs_int(&q);
il=1;
memset(tr,0,sizeof(tr));
memset(l,0,sizeof(l));
for (i=0;i<q;i++)
{
fs_int(&u);
fs_int(&v);
fs_int(&d);
tl=&l[il];
tl->next=tr[u].ch;
tl->val=v;
tl->d=d;
tr[u].ch=il++;
tl=&l[il];
tl->next=tr[v].ch;
tl->val=u;
tl->d=d;
tr[v].ch=il++;
}
//set_depth(tr,l,1,0,0);
// print(tr,l,1,0,0);
get_sum(tr,l);
ll res=1;
for (i=2;i<=n;i++)
{
res= ( (res%MOD) *(tr[i].count%MOD) )%MOD;
}
printf ("%lld\n",res);
}
return 0;
}
the function that interests you is the function get_sum(). It is a breadth first search, that in a graph means check along concentric circles, that allows you to avoid useless propagations. It store the values in this virtual circle, on an array, called reg. And at each step you are going to check forward. About the efficency you can check by your self at Ways contest. It has one of the best time